假设我们现在有两个文件 a.txt 、b.txt
a.txt 中的内容如下:
a c 1 3 d 4
b.txt 中的内容如下:
a b e 2 1 5
# example 01
计算并集:
[root@vm_81_181_centos ~]# sort -u a.txt b.txt 1 2 3 4 5 a b c d e [root@vm_81_181_centos ~]#
# exmaple 02
计算交集:
[root@vm_81_181_centos ~]# grep -f -f a.txt b.txt | sort | uniq
1
a
[root@vm_81_181_centos ~]#
# example 03
计算差集(a - b):
[root@vm_81_181_centos ~]# grep -f -v -f b.txt a.txt | sort | uniq 3 4 c d [root@vm_81_181_centos ~]#
# example 04
计算差集(b - a):
[root@vm_81_181_centos ~]# grep -f -v -f a.txt b.txt | sort | uniq 2 5 b e [root@vm_81_181_centos ~]#
上面介绍了关于如何使用 grep 命令实现文件的交、差集,但是在实际操作中得到的结果却有点问题存在
[root@vm_81_181_centos ~]# grep -f -f a.txt b.txt | sort | uniq | wc -l 4095 [root@vm_81_181_centos ~]# grep -f -f b.txt a.txt | sort | uniq | wc -l 4729 [root@vm_81_181_centos ~]#
上面的命令我是用于求 a 、b 两个文件的交集,但是当把两个文件的位置顺序改变了一下,结果竟然是不
一样,这是不科学的。
后来仔细想了想,grep 命令是搜索查找的命令,举个例子:
c.txt 文件里面的内容如下:
1122 1133 1144 1155
d.txt 文件里面的内容如下:
11223344
执行 grep 命令:
[root@vm_81_181_centos ~]# grep -f -f c.txt d.txt | sort | uniq 11223344 [root@vm_81_181_centos ~]# grep -f -f d.txt c.txt | sort | uniq [root@vm_81_181_centos ~]#
根据结果,对第一条命令的解读是:
命令执行后,在 d.txt 文件里面搜索和 c.txt 文件相匹配的字符,因为 c.txt 文件里面的字符 1122 和 d.txt 文件里面的
字符 11223344 前面的 1122 相匹配,则就把 11223344 字符作为两个文件相同的部分记录下来
第二条命令:
命令执行后,在 c.txt 文件里面搜索和 d.txt 文件相匹配的字符,d.txt 文件里面的 11223344 在 c.txt 文件里面找不到
与其类似或相同的字符,所以,结果为空。
现在,在 c.txt 文件里面新增字符 112233445566,结果及操作如下:
c.txt 文件内容:
1122 1133 1144 1155 1122334455
执行 grep 命令:
[root@vm_81_181_centos ~]# grep -f -f d.txt c.txt | sort | uniq 1122334455 [root@vm_81_181_centos ~]#
结论:
grep -f -f filea fileb | sort | uniq
当 filea 文件 在前,则表示在 fileb 文件里面搜索和 filea 文件里面相同或者类似的字符,并将 fileb 文件里面那个字符记录下来
同理,fileb 在前,filea 在后的情况。
但是,在这里这并不是我们想要的结果,我们想要的结果就是我们以前学数学时候,求两个集合的交集一样,结果输
出的是两个集合共有的部分,尝试了几个方法,最后还是选择使用 cat 命令。
命令格式如下:
cat filea fileb | sort | uniq -d # 求交集 cat filea fileb | sort | uniq -u # 求差集
这个命令比较好理解,cat 命令先把两个文件合并成一个文件,然后在对合并后的文件进行排序、去重,-d 命令输出文
件中相同的字符,-u 命令输出文件中不同的字符,并且 在计算交集的时候 filea、fileb 文件顺序哪个在前在后的结果都是一样的。
案例如下:
[root@vm_81_181_centos ~]# cat c.txt 1122 1133 1144 1155 1122334455 [root@vm_81_181_centos ~]# cat d.txt 11223344 1122 [root@vm_81_181_centos ~]#
c、d 文件内容如上
执行 cat 命令求交集:
[root@vm_81_181_centos ~]# cat c.txt d.txt | sort | uniq -d 1122 [root@vm_81_181_centos ~]# cat d.txt c.txt | sort | uniq -d 1122 [root@vm_81_181_centos ~]#
执行 cat 命令求差集:
[root@vm_81_181_centos ~]# cat c.txt d.txt | sort | uniq -u 11223344 1122334455 1133 1144 1155 [root@vm_81_181_centos ~]# cat d.txt c.txt | sort | uniq -u 11223344 1122334455 1133 1144 1155 [root@vm_81_181_centos ~]#
但是 cat 命令也有一个短板,当文件比较大的时候,就会出错,但是在这里我们可以去借助
split 命令对文件进行分割,分而治之,然后合并,关于如何使用 split 命令,可以参考我的这篇文章
paste命令
按列合并文件
paste 格式为:
paste -d -s -file1 file2
选项含义如下:
-d 指定不同于空格或tab键的分隔符,例如使用@分隔符,使用 -d @
-s 将每个文件合并成行而不是按行粘贴
- 使用标准输入。例如:ls -l | paste 意思是只在一列上显示输出
例子:
#cat pas1 id897 id666 id982 #cat pas2 p.jones s.round l.clip
基于 paste 命令将 pas1.txt 和 pas2.txt 两文件粘贴成两列:
# paste pas1 pas2 id897 p.jones id666 s.round id982 l.clip
通过交换文件名即可指定哪一列先粘贴:
# paste pas2 pas1 p.jones id897 s.round id666 l.clip id982
要创建不同于空格或tab键的分隔符,使用 -d 选项,如下使用冒号做分隔符:
# paste -d: pas2 pas1 p.jones:id897 s.round:id666 l.clip:id982
要将两列合并成两行,需要使用 -s 选项,如下例子:
# paste -s pas1 pas2 id897 id666 id982 p.jones s.round l.clip