Linux

存在於一個文件中但不存在於另一個文件中的 grep 行

  • July 10, 2018

我正在嘗試做簡單的事情grepgrep -v所以我會從中得到a.txt那些存在於b.txt而不是c.txt.

3 個文件的範例

a.txt:

a
b
c
d
e

up.txt:

a.up
b.up
c.up

dw.txt:

a.dw
b.dw

期望的輸出:

c

我寫了下面的程式碼,但grep看起來$(sed...) 一次是一行,而不是一個整體:

sed 's/.up//' /tmp/b.txt | grep -f /tmp/a.txt | grep -vf $(sed 's/.dw//' /tmp/c.txt)

假設所有文件都已排序,並且我們使用的 shell 可以理解程序替換(如bash):

$ join -t . -v 1 -o 0 <( join -t . a.txt b.txt ) c.txt
c

或者,對於其他貝殼,

$ join -t . a.txt b.txt | join -t . -v 1 -o 0 - c.txt
c

這使用join兩次來執行文件之間的關係連接。數據被解釋為以點分隔的欄位(帶有-t .)。

a.txt和之間的連接b.txt是直截了當的,產生

a.up
b.up
c.up

這些是兩個文件中的所有行,其第一個點分隔欄位出現在兩個文件中。輸出由連接欄位 ( a, b, c) 組成,後跟來自兩個文件的其他欄位(只有b.txt任何進一步的數據)。

第二個連接有點特別。-v 1我們要求查看第一個文件(上面的中間結果)中不能與第二個文件中的任何行配對的條目,c.txt. 此外,我們只要求查看連接欄位本身 ( -o 0)。沒有-o標誌,我們將得到c.up結果。


如果文件未排序,則文件名的每次出現file都可以<( sort file )在命令中替換為。

使用單個快速 GNU**awk**命令:

awk -F'.' \
'{
    if (ARGIND == 1) a[$1];
    else if (ARGIND == 2 && $1 in a) comm[$1];
    else if (ARGIND == 3){
        delete a;
        if ($1 in comm) delete comm[$1]
    }
}
END{ for (i in comm) print i }' a.txt b.txt c.txt

輸出:

c

  • -F'.'-.視為欄位分隔符
  • ARGIND``ARGV-正在處理的目前文件(命令行參數數組)中的索引
  • comm-前 2 個文件 (和)之間的公共項目數組a.txt``b.txt

引用自:https://unix.stackexchange.com/questions/454137