Grep

grep 如何返回不同數量的匹配項?

  • September 3, 2021

我需要將一個文件(24 行)grep 成兩個文件(有點大)。

原始文件包含 24 行類似於此字元串:

AATGGACGCTTAAC[A|C|T][A|C|G]CGGC[A|T]TCGGAT

我執行以下操作:

grep -f aList hugeFile_N*.csv | wc -l
4396868

然後,為了仔細檢查一切是否正常,我將文件分成兩個文件,並通過另一個 grep 使用它們:

cat aList | head -n 12 > firstHalf
cat aList | tail -n +13 > secondHalf
grep -f firstHalf hugeFile_N*.csv | wc -l
2169008
grep -f secondHalf hugeFile_N*.csv | wc -l
2228046

現在,我期望來自兩個單獨的 grepped 文件的匹配總數將等於我為原始文件找到的匹配數。但是,如您所見:

2169008 + 2228046 = 4397054
4397054 != 4396868

不是這種情況。我們有 186 場比賽失去。這裡發生了什麼?

我還對(實際上非常簡單的)文件進行了一些調查。在這裡,我從兩個單獨的部分 grep 的結果:

grep -f <(cat firstHalf secondHalf) hugeFile_N*.csv > together

然後我分別 grep 兩半:

grep -f firstHalf hugeFile_N*.csv > separately
grep -f secondHalf hugeFile_N*.csv >> separately

而且,如前所述,匹配的數量是不同的:

wc -l together
4396868 together
wc -l separately
4397054 separately

但是,唯一匹配的數量是相同的:

sort -u together | wc -l
3735836
sort -u separately | wc -l
3735836

有趣的是,如果我 grep 原始文件中的兩半,我根本沒有匹配項。我想知道為什麼會這樣:

grep -f ../code/firstHalf ../code/aList | wc -l
0
grep -f ../code/secondHalf ../code/aList | wc -l
0

我 100% 確定兩半都存在,aList因為我可以用我的編輯器看到它(它們每行 12 行,所以肉眼甚至不難看到)。

我覺得我做錯了grep什麼但是……什麼?

裡面的所有線條aList都是獨一無二的。

grep只查找至少匹配給定模式之一的行。中的24 個模式aList,可能前半場中的一個和後半場中的一個匹配。這意味著您將在同一行上獲得 和 的匹配grep -f firstHalfgrep -f secondHalf。分別執行模式列表的兩半會加倍計算這些行。

例如

$ cat test.txt 
abc 
foo
bar
foobar
$ cat patterns 
foo
bar
$ grep -c -f patterns  test.txt 
3

但當然還有:

$ grep -c -e foo test.txt
2
$ grep -c -e bar test.txt
2

並且 2+2 > 3。

如果所有行都不同,那麼計算唯一匹配行當然是消除這種影響的一種方法。您可以使用grep -n將行號添加到輸出中,使每個輸出行都是唯一的。當然請記住,預設情況下grep會在行中的任何位置查找匹配項,如果這不是您想要的,您需要使用grep -x.

另請注意,這意味著[A|C|T]匹配任何字元A、或。如果您不想或不需要匹配管道字元,請使用. 或者,如果您需要交替,則必須使用擴展的正則表達式 ( ),然後(帶括號,而不是括號)。但這不是必需的,只要所有替代項都是單個字元。C``T``|``[ACT]``grep -E``(this|that)

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