曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 3266|回复: 0
打印 上一主题 下一主题

uniq -- 报告或忽略重复行

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2012-3-24 14:57:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
uniq 命令用从给定输入中来找出唯一的行,而忽略或排除掉重复的行,当然反过来也可以找到重复的行而去掉唯一的行。需要注意的是,uniq 只能应用于被排序了的文本(参考 sort  命令),因此 uniq 大多数情况下总是和 sort命令搭配使用。

比如对于下面的一个文本:
# cat tmp.txt
welcome
groad
to
www
groad
net
里面的有一个重复行 groad,如果直接对该文件使用 uniq 命令,那么会毫无改变的输出:
# cat tmp.txt
welcome
groad
to
www
groad
net
如果我们将重复的 groad 放到一起:
# cat tmp.txt
welcome
to
www
groad
groad
net
然后再直接对其使用 uniq 命令,那么会看到:
# uniq tmp.txt
welcome
to
www
groad
net
上面发现,重复的一行 groad 被去掉了。

如果希望只打印出唯一而没有重复的行,可用 -u 选项:
# uniq -u tmp.txt
welcome
to
www
net

像前面所说,uniq 命令只对排序后的文件起作用,因此假如上面的 tmp.txt 文件若是还没有被排序,那么我们可以:
$ sort tmp.txt | uniq -u

类似地,如果只想列出重复的行,那么使用 -d 选项:
# uniq -d tmp.txt
groad


还可以使用 -c 选项对每一行的行数进行统计:
# uniq -c tmp.txt
      1 welcome
      1 to
      1 www
      2 groad
      1 net

另外还有 -s 和 -w 这两个选项经常会结合使用,其中:

-s 表示指定忽略前面几个字符;

-w 表示最大比较多少个字符。

下面是重新设计的一个文本:
# cat temp.txt
a:01:linux
b:03:unix
c:01:windows
b:04:ucosii
a:03:macios
对上面的文本直接用 sort :
# sort temp.txt
a:01:linux
a:03:macios
b:03:unix
b:04:ucosii
c:01:windows
我们可以将排序的结果通过管道使用 uniq 的 -w 选项:
# sort temp.txt | uniq -s 2 -w 2
a:01:linux
a:03:macios
b:04:ucosii
c:01:windows
由上面输出可见,当排序后的内容通过管道后,首先被 -s 的选项要求忽略前面的 2 个字符,接着又被要求最大比较 2 个字符,因此这里实际比较的是 01, 03 这些数字是否发生重复,正如上面所见,有两个 03 的行排在一块,即发生了重复,因此得到了上面的输出。

此外,uniq 的 -z 选项会使 uniq 的输出是以 '\0' 结尾的,使用该选项的目的往往是在下一步的处理中将该处理结果通过管道输送到 xargs 命令中。如果没有 '\0' 作为结尾,那么对于 xargs 来说,空格字符就是默认的间隔符,这样在解析中就容易出现错误。比如 "welcome to groad" 会被 xargs 认为是 3 个独立的参数,但当这个字符串以 '\0' 作为结尾,那么它就会被认为是单独的一个参数。比如:
uniq -z tmp.txt | xargs -0 rm -f

关于 xargs 命令中的 -0 选项及更多信息可参考:http://www.groad.net/bbs/read.php?tid-498.html

下面的例子中,我们用 uniq 结合其它命令来统计一个字符串中重复的字符个数,假设有一个字符串为:akoqaaboooozkk 。

如下运行命令:
# echo "akoqaaboooozkk" | sed 's/[^\n]/&\n/g' | sed '/^$/d' | sort | uniq -c
      3 a
      1 b
      3 k
      5 o
      1 q
      1 z
还可以进一步写成:
# echo "akoqaaboooozkk" | sed 's/[^\n]/&\n/g' | sed '/^$/d' | sort | uniq -c | tr -d ' \n'
3a1b3k5o1q1z
在上面的命令中,当字符串通过管道后,sed 查找只要非换行字符,找到后使用 &\n 进行替换,其中 & 表示匹配非换行部分,即保留该字符,因此 &\n 表示在保留的字符后再添加一个换行。在这样处理后,最后还会产生一个换行,亦即一个空行,因此让它再次通过管道用 sed 删除掉。然后使用 sort 进行排序,最后用 uniq 的 -c 选项统计重复的个数。这个统计重复字符的方法称为“分解统计法”。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-6-18 04:00 , Processed in 0.113857 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表