前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >如何用 awk 删除文件中的重复行【Programming】

如何用 awk 删除文件中的重复行【Programming】

作者头像
Potato
修改2019-11-11 11:07:42
修改2019-11-11 11:07:42
8.7K00
代码可运行
举报
运行总次数:0
代码可运行

了解如何在不排序或更改其顺序的情况下使用awk'!visited $ 0 ++'。

假设您有一个文本文件,并且需要删除它的所有重复行。

摘要

要删除重复的行,同时保留它们在文件中的顺序,请使用:

代码语言:txt
复制
awk '!visited[$0]++' your_file > deduplicated_file

工作原理

该脚本会保留一个关联数组,其索引等于文件的唯一行,而值等于它们的出现次数。 对于文件的每一行,如果行出现次数为零,则将其增加一并打印该行,否则,它仅增加出现次数而无需打印该行。

我对awk并不熟悉,所以我想了解它是如何通过这么短的脚本来实现这一点的。我做了研究发现以下几点:

  • 输入文件的每一行都会执行awk“脚本”!visited[$0]++。
  • visit []是类型为关联数组 (又称为Map )的变量。 我们不必初始化它,因为awk会在我们第一次访问它时进行初始化。
  • $0变量用于保存当前正在处理的行的内容。
  • visited [ $0]访问存储在映射中的值,其键值等于$0(正在处理的行),也称为匹配项(我们将会在下面设置)。
  • 取非(!)的值:在awk中,任何非零数字值或任何非空字符串值均为true 。默认情况下,变量被初始化为空字符串,如果转换为数字则为零。换言之:如果visit [[0]]返回大于零的数字,则此否定结果为false 。如果visit [[0]]返回一个等于零的数字或一个空字符串,则该否定结果将解析为true 。
  • ++操作将变量的值( Visited [$ 0] )加1。如果该值为空, awk会自动将其转换为0 (数字),然后将其增加。(注意:在我们访问变量的值之后执行操作)

综上所述,整个表达式的计算结果是:

  • 如果事件为零 / 空字符串,则返回true
  • 如果出现的次数大于零,则返回false

awk语句由一个模式-表达式和一个关联的操作组成 。

代码语言:javascript
代码运行次数:0
复制
< pattern / expression > { < action > }

如果模式正确,则执行相关的操作。 如果我们不提供操作,awk 默认情况下会打印输入。省略操作等价于{ print $0}。

我们的脚本由一个 awk 语句和一个表达式组成,省略了操作。 所以这样:

代码语言:javascript
代码运行次数:0
复制
awk '!visited[$0]++' your_file > deduplicated_file

等同于:

代码语言:javascript
代码运行次数:0
复制
awk '!visited[$0]++ { print $0 }' your_file > deduplicated_file

对于文件的每一行,如果表达式成功,则将该行打印到输出。否则,不执行操作,也不打印任何内容。

为什么不使用 uniq 命令?

uniq命令仅除去相邻的重复行 。 下面是例子:

代码语言:javascript
代码运行次数:0
复制
$ 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 命令来删除重复的行,但不保留行顺序。

代码语言:javascript
代码运行次数:0
复制
sort -u your_file > sorted_deduplicated_file

使用cat,sort和cut

前面的方法将生成一个去重复的文件,其行将根据内容进行排序。 利用管道符连接一堆命令可以解决这个问题:

代码语言:javascript
代码运行次数:0
复制
cat -n your_file | sort -uk2 | sort -nk1 | cut -f2-

工作原理

假设我们有以下文件:

代码语言:javascript
代码运行次数:0
复制
abc
ghi
abc
def
xyz
def
ghi
klm

“cat -n test.txt”在每行前添加序号。

代码语言:javascript
代码运行次数:0
复制
1 abc
2 ghi
3 abc
4 def
5 xyz
6 def
7 ghi
8 klm

sort -uk2根据第二列对行进行排序 ( k2选项),并且只保留第一次出现的具有相同第二列值的行(u 选项)。

代码语言:javascript
代码运行次数:0
复制
1 abc
4 def
2 ghi
8 klm
5 xyz

Sort-nk1根据行的第一列(k1选项)对行进行排序,并将该列视为数字(- n 选项)。

代码语言:javascript
代码运行次数:0
复制
1 abc
2 ghi
4 def
5 xyz
8 klm

最后,cut-f2从第二列开始打印到结束(-f2-选项: 注意-后缀,指示其包括其余的行)。

代码语言:javascript
代码运行次数:0
复制
abc
ghi
def
xyz
klm

参考资料

最后是可爱的猫咪。

本文系外文翻译,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系外文翻译前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 摘要
  • 工作原理
  • 为什么不使用 uniq 命令?
  • 其他方法
    • 使用sort命令
    • 使用cat,sort和cut
    • 工作原理
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档