文件查看编辑命令 uniq
uniq 命令在 Linux 中是一个非常有用的工具,通常用于去除相邻的重复行。
不过,有一个很重要的前提:uniq
只能处理相邻的重复行。这意味着,如果重复的行不是紧挨着的,uniq
会把它们当成不同的行。
为了让 uniq
能正确地处理所有重复行,我们通常会先用 sort
命令对内容进行排序,确保所有相同的行都排列在一起。
1. 基本用法:去除相邻的重复行
最基本的用法就是直接使用 uniq
命令,它会读取文件内容,然后输出一份去除了相邻重复行的版本。
假设我们有一个文件 fruits.txt
,内容如下:
apple
banana
apple
orange
banana
banana
直接对它使用 uniq
:
uniq fruits.txt
你会得到下面的输出:
apple
banana
apple
orange
banana
注意到第一个 apple
和第二个 apple
并没有被当成重复项,因为它们中间隔着一行 banana
。这就是为什么我们通常需要先 sort
。
2. 先排序再处理:最常见的用法
这是 uniq
最经典的使用场景。我们通过管道符 |
把 sort
命令的输出结果直接传给 uniq
命令。
我们还是用上面的 fruits.txt
文件。
sort fruits.txt | uniq
sort fruits.txt
会先输出:
apple
apple
banana
banana
banana
orange
然后 uniq
再处理这个排好序的结果,最终的输出就是:
apple
banana
orange
这样就实现了真正意义上的“全文去重”。
3. 统计每一行出现的次数
如果你不仅想去重,还想知道每一行到底出现了多少次,可以使用 -c
(count) 选项。
sort fruits.txt | uniq -c
输出结果会在每一行的前面加上一个数字,表示它在排序后的文件中连续出现的次数。
2 apple
3 banana
1 orange
这个命令对于快速统计日志中某个事件的发生频率非常有用。
4. 只显示重复过的行
有时候你可能只关心哪些行是重复出现的,不关心那些只出现一次的行。这时候可以用 -d
(duplicated) 选项。
sort fruits.txt | uniq -d
这个命令会只输出那些至少出现过两次的行(去重后)。
apple
banana
5. 只显示唯一的行
和 -d
相反,-u
(unique) 选项会只显示那些从头到尾只出现过一次的行。
sort fruits.txt | uniq -u
使用我们的例子,只有 orange
是独一无二的。
orange
6. 忽略大小写差异
默认情况下,uniq
是大小写敏感的('Apple' 和 'apple' 会被认为是不同的行)。如果你想在比较时忽略大小写,可以使用 -i
(ignore-case) 选项。
假设我们有一个文件 names.txt
:
Alex
alex
Bob
Chris
Bob
如果我们直接 sort | uniq
:
sort names.txt | uniq
输出会是:
Alex
Bob
alex
Chris
Alex
和 alex
被当成了不同的行。现在我们加上 -i
选项:
sort names.txt | uniq -i
输出就变成了:
Alex
Bob
Chris
注意:sort
命令本身也需要忽略大小写才能把 Alex
和 alex
排在一起,所以更严谨的写法是 sort -f names.txt | uniq -i
。
7. 跳过开头的指定字段
在处理一些格式化的文本(比如日志文件)时,你可能想基于某一列或某几列来判断是否重复,而不是整行比较。uniq
提供了 -f
(fields) 选项来跳过行首的若干个字段。字段默认是由空格或制表符分隔的。
假设我们有一个日志文件 log.txt
,记录了用户的操作:
10:00 user1 login
10:02 user2 login
10:03 user1 logout
10:05 user1 login
我们想找出哪些用户执行了连续相同的操作,但要忽略时间戳。我们可以跳过第一个字段(时间戳)。
uniq -f 1 log.txt
输出:
10:00 user1 login
10:02 user2 login
10:03 user1 logout
10:05 user1 login
在这个例子里,uniq
会从 user1
开始比较 10:00 user1 login
和 10:02 user2 login
,因为它们不同,所以都保留。它也会从 user1
开始比较 10:03 user1 logout
和 10:05 user1 login
,也不同。
如果我们只想找出连续登录的用户,可以这样:
# 假设有这样的日志
10:00 user1 login
10:01 user1 login
10:02 user2 login
uniq -f 1 log_with_duplicates.txt
它会跳过时间字段,发现 user1 login
是重复的,于是只保留第一条。
8. 跳过开头的指定字符
除了可以跳过字段,你还可以用 -s
(skip-chars) 选项来精确地跳过行首的指定数量的字符。
假设文件 data.txt
内容如下,每一行的前5个字符是编号,我们想忽略编号来去重。
abc01:apple
abc03:apple
abc02:banana
然后用 uniq
跳过前6个字符(abc01:
)。
uniq -s 6 data.txt
它会把第一行和第二行看作是相同的(因为都剩下 apple
),所以输出会是:
abc01:apple
abc02:banana
当 -f
和 -s
一起使用时,会先跳过 -f
指定的字段,然后再在剩下的内容里跳过 -s
指定的字符。