Linux shell 計算兩個文件的並集、交集、差集


假設我們現在有兩個文件 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 ~]#

 

 

-----------------------------------------------------------手動分割線---------------------------------------------------------------------------

2018/09/30 更新

上面介紹了關於如何使用 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 命令,可以參考我的這篇文章

傳送門:https://www.cnblogs.com/leeyongbard/p/9594439.html

 

----------------------------------------------2019/04/27------------------------------------------------------------

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 

有不同意見,歡迎交流^_^


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM