comm 命令介绍

目录

有这样一个需求文件 1.txt 2.txt 每个文件大概有 10 万行字符串,我们现在需要知道只存在 1.txt 中的字符串,这时可以用 comm 这个命令。

普通脚本

# 我们可以直接用普通脚本实现,但是却花了 6 分钟时间
# 这样做的主要好处是可以不用对文件进行任何预处理
jimila@CDYJY-JINGML:tim$ time cat 1.txt |while read line ; do if ! $(grep $line 2.txt >/dev/null) ; then echo $line >> 3.txt ; fi  ; done

并发执行

可以用 这种 方式提升处理速度

jimila@CDYJY-JINGML:tim$ mkfifo /run/shm/map.p
jimila@CDYJY-JINGML:tim$ cat 1.txt > /run/shm/map.p
# 我一共开了 4 个窗口执行下面的命令,就只需要差不多 1.5 分钟的样子就执行完了,开 6 个估计只需要 1 分钟
jimila@CDYJY-JINGML:tim$ time cat /run/shm/map.p |while read line ; do if ! $(grep $line 2.txt >/dev/null) ; then echo $line >> 3.txt ; fi  ; done

real  1m16.324s
user  0m1.484s
sys 0m2.924s

使用 comm

预处理文本

# 首先我们要确保 1.txt 2.txt 的文件是排序了的,而且没有重复行,另外我们要确保文件的编码是 utf-8 或者 anscii 的
# 先看一下我们要处理的文件编码
jimila@CDYJY-JINGML:tim$ file 1.txt 2.txt 
1.txt: ISO-8859 text
2.txt: Non-ISO extended-ASCII text, with CRLF line terminators

# 可以看出是 gbk 的编码,这时我们需要转换一下编码
jimila@CDYJY-JINGML:tim$ iconv -f gbk -t utf8 1.txt -o 11.txt 
jimila@CDYJY-JINGML:tim$ iconv -f gbk -t utf8 2.txt -o 22.txt 

# 然后我们需要对文件进行排序和去重处理
jimila@CDYJY-JINGML:tim$ cat 11.txt |sort |uniq > 111.txt
jimila@CDYJY-JINGML:tim$ cat 22.txt |sort |uniq > 222.txt

执行 comm

# 这时我们已经得到了满足我们需要的文件 111.txt 222.txt
# 直接执行下面命令我们会得到 3 列输出,第一列:只存在 111.txt 文件的行。第二列:只存在 222.txt 的行。第三列:是 111.txt 222.txt 文件中都有的行
jimila@CDYJY-JINGML:tim$ comm 111.txt 222.txt

# 如果我们要得到只在 111.txt 的数据就使用 -23 表示去掉第二,三列的输出,同理-12 表示得到文件 111.txt 222.txt 数据的交集。
jimila@CDYJY-JINGML:tim$ comm -23 111.txt 222.txt


# 我们可以看到处理的效率非常高处理 10 万行的数据只需要 0.1s
jimila@CDYJY-JINGML:tim$ time comm -23 111.txt 222.txt >/dev/null

real  0m0.183s
user  0m0.180s
sys 0m0.004s


目录