利用 sort 和 uniq 做集合运算


原文链接: 利用 sort 和 uniq 做集合运算

最佳搭档:利用 sort 和 uniq 做集合运算 | 始终

sort: 生而为排序

sort 命令的用法很简单。最基本的用法有两种:

cat | sort
sort [ [ [...]]]

二者意义相同:sort 会逐行读入文件内容;然后依 ASCII 编码的顺序,升序排列文件的行;最后输出到标准输出(通常是屏幕)。注意,sort 可以连续读入多个文件,而后合在一起排序。

如果希望将 sort 结果保存到文件,则需要用到 -o 选项(当然,大多数情况也可以用 > 重定向):

sort -o

如果希望倒序排列,则需要用到 -r 选项:

sort -r

对于数字来说,按照 ASCII 编码排列就不合适了,此时可以用到 -n 选项:

sort -n

其他选项:

-u 去除重复行
-t 指定分隔符(通常与 -k 联用)
-k 指定用于排序的列号
-f 忽略大小写
-M 能够排序月份
-b 忽略行首空白

uniq: 专治重复,一针见效

uniq 的作用可以描述为:针对相邻的重复行,进行相应的动作。

这句话中,有两个地方需要注意。首先,针对的是相邻的重复行。因此,uniq 对于不相邻的重复行是不起作用的。其次,进行相应的动作。这意味着,uniq 可以做的事情很多,不止一样。

不带任何参数的时候 uniq 的动作是:对相邻的重复行进行去除。例如:

cat | sort | uniq

我们已经见过了 sort 的作用,那么上面命令的作用就很显然了:将 按照 ASCII 升序排序;然后去除重复出现的行;最后将这个没有重复行的内容输出到标准输出。

给 uniq 加上参数,就能解锁更多姿势。

cat | sort | uniq -d # 只显示重复的行,每行只显示一次
cat | sort | uniq -D # 只显示重复的行
cat | sort | uniq -i # 忽略大小写
cat | sort | uniq -u # 只显示只出现一次的行
cat | sort | uniq -c # 统计每行重复的次数

集合运算

接下来,我们强行将 sort 和 uniq 凑到一起,看看会发生什么。

求交集

交集就是两个集合都出现的那些元素。放到我们的场景里,就是两个文件重复出现过的行。毫无疑问,我们需要 uniq 的 -d 选项。

sort | uniq -d # 交集

求并集

并集就是两个集合的元素加起来,去掉重复的部分。uniq 就是为此而生的。

sort | uniq # 并集

求差集

A∖B=x∣x∈A∧x∉B
,也就是存在于 A 但不存在于 B 的那些。简而言之,这是一个在集合 A

中找到最高贵冷艳的元素的过程。

只要重复了,那就不叫高贵冷艳。同时我们知道,重复一次叫重复;重复两次,那也还是重复。因此,我们只需要将 和两份 放在一起,寻找只出现过一次的行就可以了。

sort | uniq -u # 差集

求对称差

A△B=(A∪B)−(A∩B)

。上面已经求得了并集和交集,所以在此基础上求一个差集就好了对吧——你疯啦!?

对称差,就是要找到两个集合放在一起,也只出现了一次的那些元素。因此只需要简单的 -u 选项就好了。

sort | uniq -u # 对称差集

`