怎样使用 awk 删掉文件中重复的行
创始人
2024-03-02 04:11:18
0

学习怎样使用 awk 的 !visited[$0]++ 在不重新排序或改变原排列顺序的前提下删掉重复的行。

假设你有一个文本文件,你需要删掉所有重复的行。

TL;DR

要保持原来的排列顺序删掉重复行,使用:

awk '!visited[$0]++' your_file > deduplicated_file

工作原理

这个脚本维护一个关联数组,索引(键)为文件中去重后的行,每个索引对应的值为该行出现的次数。对于文件的每一行,如果这行(之前)出现的次数为 0,则值加 1,并打印这行,否则值加 1,不打印这行。

我之前不熟悉 awk,我想弄清楚这么短小的一个脚本是怎么实现的。我调研了下,下面是调研心得:

  • 这个 awk “脚本” !visited[$0]++ 对输入文件的每一行都执行。
  • visited[] 是一个关联数组(又名映射)类型的变量。awk 会在第一次执行时初始化它,因此我们不需要初始化。
  • $0 变量的值是当前正在被处理的行的内容。
  • visited[$0] 通过与 $0(正在被处理的行)相等的键来访问该映射中的值,即出现次数(我们在下面设置的)。
  • ! 对表示出现次数的值取反:
    • awk 中,任意非零的数或任意非空的字符串的值是 true
    • 变量默认的初始值为空字符串,如果被转换为数字,则为 0。
    • 也就是说:
      • 如果 visited[$0] 的值是一个比 0 大的数,取反后被解析成 false
      • 如果 visited[$0] 的值为等于 0 的数字或空字符串,取反后被解析成 true
    • ++ 表示变量 visited[$0] 的值加 1。
      • 如果该值为空,awk 自动把它转换为 0(数字) 后加 1。
      • 注意:加 1 操作是在我们取到了变量的值之后执行的。

总的来说,整个表达式的意思是:

  • true:如果表示出现次数为 0 或空字符串
  • false:如果出现的次数大于 0

awk模式或表达式和一个与之关联的动作 组成:

<模式/表达式> { <动作> }

如果匹配到了模式,就会执行后面的动作。如果省略动作,awk 默认会打印(print)输入。

省略动作等价于 {print $0}

我们的脚本由一个 awk 表达式语句组成,省略了动作。因此这样写:

awk '!visited[$0]++' your_file > deduplicated_file

等于这样写:

awk '!visited[$0]++ { print $0 }' your_file > deduplicated_file

对于文件的每一行,如果表达式匹配到了,这行内容被打印到输出。否则,不执行动作,不打印任何东西。

为什么不用 uniq 命令?

uniq 命令仅能对相邻的行去重。这是一个示例:

$ cat test.txt
A
A
A
B
B
B
A
A
C
C
C
B
B
A
$ uniq < test.txt
A
B
A
C
B
A

其他方法

使用 sort 命令

我们也可以用下面的 sort 命令来去除重复的行,但是原来的行顺序没有被保留

sort -u your_file > sorted_deduplicated_file

使用 cat + sort + cut

上面的方法会产出一个去重的文件,各行是基于内容进行排序的。通过管道连接命令可以解决这个问题。

cat -n your_file | sort -uk2 | sort -nk1 | cut -f2-

工作原理

假设我们有下面一个文件:

abc
ghi
abc
def
xyz
def
ghi
klm

cat -n test.txt 在每行前面显示序号:

1       abc
2       ghi
3       abc
4       def
5       xyz
6       def
7       ghi
8       klm

sort -uk2 基于第二列(k2 选项)进行排序,对于第二列相同的值只保留一次(u 选项):

1       abc
4       def
2       ghi
8       klm
5       xyz

sort -nk1 基于第一列排序(k1 选项),把列的值作为数字来处理(-n 选项):

1       abc
2       ghi
4       def
5       xyz
8       klm

最后,cut -f2- 从第二列开始打印每一行,直到最后的内容(-f2- 选项:留意 - 后缀,它表示这行后面的内容都包含在内)。

abc
ghi
def
xyz
klm

参考

以上为全文。


via: https://opensource.com/article/19/10/remove-duplicate-lines-files-awk

作者:Lazarus Lazaridis 选题:lujun9972 译者:lxbwolf 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

awk

相关内容

不要在awk中转义变量
在awk中使用变量时,不需要像其他编程语言那样在变量前加上$符号。...
2025-01-11 01:01:02
不同文件之间的awk求和结...
要实现不同文件之间的awk求和结果保存在不同文件中,可以使用awk...
2025-01-09 21:01:44
不同的AWK版本具有不同的...
在不同的AWK版本中,最小的双精度值可能会有所不同。一种解决方法是...
2025-01-08 12:01:37
不使用排序进行比较两个文件...
以下是一个不使用排序进行比较两个文件的AWK解决方法的示例代码:#...
2024-12-29 05:01:00
不使用awk或sed进行文...
在Python中,我们可以使用标准库中的fileinput模块来实...
2024-12-28 10:31:22
部分匹配两个不同文件中的单...
下面是使用sed、awk和grep来部分匹配两个不同文件中的单词,...
2024-12-24 06:02:07

热门资讯

Helix:高级 Linux ... 说到 基于终端的文本编辑器,通常 Vim、Emacs 和 Nano 受到了关注。这并不意味着没有其他...
使用 KRAWL 扫描 Kub... 用 KRAWL 脚本来识别 Kubernetes Pod 和容器中的错误。当你使用 Kubernet...
JStock:Linux 上不... 如果你在股票市场做投资,那么你可能非常清楚投资组合管理计划有多重要。管理投资组合的目标是依据你能承受...
通过 SaltStack 管理... 我在搜索Puppet的替代品时,偶然间碰到了Salt。我喜欢puppet,但是我又爱上Salt了:)...
Epic 游戏商店现在可在 S... 现在可以在 Steam Deck 上运行 Epic 游戏商店了,几乎无懈可击! 但是,它是非官方的。...
《Apex 英雄》正式可在 S... 《Apex 英雄》现已通过 Steam Deck 验证,这使其成为支持 Linux 的顶级多人游戏之...
如何在 Github 上创建一... 学习如何复刻一个仓库,进行更改,并要求维护人员审查并合并它。你知道如何使用 git 了,你有一个 G...
2024 开年,LLUG 和你... Hi,Linuxer,2024 新年伊始,不知道你是否已经准备好迎接新的一年~ 2024 年,Lin...
什么是 KDE Connect... 什么是 KDE Connect?它的主要特性是什么?它应该如何安装?本文提供了基本的使用指南。科技日...
Opera 浏览器内置的 VP... 昨天我们报道过 Opera 浏览器内置了 VPN 服务,用户打开它可以防止他们的在线活动被窥视。不过...