怎样使用 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

热门资讯

“Linux 中国” 开源社区... 这是一个艰难的决定 —— 这不是调侃,而是当你真正做出改变了你十几年生活轨迹的决定时,你就会明白这个...
硬核观察 #1263 德国铁路... #1 德国铁路公司招聘 Windows for Workgroups 3.11 管理员该职位要求了解...
人工智能教程(七):Sciki... 在本系列的 上一篇文章 中,我们用 TensorFlow 构建了第一个神经网络,然后还通过 Kera...
关闭 WSL 中正在运行的 L... 以下是使用 WSL 关闭在 Windows 内运行的 Linux 系统的不同方法。你使用 WSL 在...
MX Linux 23.2 “... 最新的 MX Linux 23.2 小版本更新带来了基本的改进和新增功能。MX Linux 推出了 ...
硬核观察 #1262 网络上最... #1 网络上最古老的软件存档库之一即将关闭美国新墨西哥州立大学(NMSU)最近宣布,即将于 2024...
如何在 RHEL 上通过绑定配... 在 Linux 中,你可以根据自己的需要创建高级网络设置,如 网络绑定 Network Bondin...
Linux Matrix 消息... Matrix 用户可以升级 Fractal 6 了!Fractal 是目前 最好的 Matrix 客...
如何通过 VLC 使用字幕 使用 VLC 媒体播放器播放和管理字幕的新手指南。我是一个超级动漫迷,如果你想观看最新的剧集,那么你...
硬核观察 #1261 X 计划... #1 X 计划在奥斯汀建立内容审核总部据报道,该部门将招聘 100 名全职员工,将主要关注 CSE ...