搜尋存在兩個不同單詞的文本文件(任何順序,任何行)
我正在尋找一種方法來搜尋同一文件中存在兩個單詞實例的文件。到目前為止,我一直在使用以下內容來執行我的搜尋:
find . -exec grep -l "FIND ME" {} \;
我遇到的問題是,如果“FIND”和“ME”之間沒有一個空格,則搜尋結果不會產生文件。我如何調整以前的搜尋字元串,其中“FIND”和“ME”兩個詞都存在於文件中,而不是“FIND ME”?
我正在使用 AIX。
使用 GNU 工具:
find . -type f -exec grep -lZ FIND {} + | xargs -r0 grep -l ME
你可以標準地做:
find . -type f -exec grep -q FIND {} \; -exec grep -l ME {} \;
grep
但是每個文件最多可以執行兩個s。為了避免執行那麼多grep
s 並且仍然可以移植,同時仍然允許文件名中包含任何字元,您可以執行以下操作:convert_to_xargs() { sed "s/[[:blank:]\"\']/\\\\&/g" | awk ' { if (NR > 1) { printf "%s", line if (!index($0, "//")) printf "\\" print "" } line = $0 }' END { print line }' } export LC_ALL=C find .//. -type f | convert_to_xargs | xargs grep -l FIND | convert_to_xargs | xargs grep -l ME
想法是將輸出轉換
find
為適合 xargs 的格式(期望空白(在語言環境中為 SPC/TAB/NLC
,在其他語言環境中為 YMMV)分隔的單詞列表,其中單引號、雙引號和反斜杠可以轉義空格,並且每個其他)。通常,您不能對 的輸出進行後處理
find -print
,因為它用換行符分隔文件名,並且不會轉義文件名中的換行符。例如,如果我們看到:./a ./b
我們無法知道它是在一個被呼叫
b
的目錄中呼叫的一個文件,a<NL>.
還是它是兩個文件a
並且b
在目前目錄中。通過使用
.//.
, 因為//
不能以其他方式出現在文件路徑中作為輸出find
(因為不存在具有空名稱的目錄並且/
不允許在文件名中),我們知道如果我們看到包含 的行//
,那麼那就是新文件名的第一行。所以我們可以使用該awk
命令來轉義所有換行符,但那些行之前的換行符除外。如果我們採用上面的範例,
find
將在第一種情況下輸出(一個文件):.//a ./b
哪個 awk 逃逸到:
.//a\ ./b
因此,這
xargs
將其視為一個論點。在第二種情況下(兩個文件):.//a .//b
哪個
awk
會保持原樣,所以xargs
看到兩個論點。您需要
LC_ALL=C
sosed
,awk
(和一些實現xargs
)適用於任意字節序列(即使在使用者的語言環境中不形成有效字元),以將空白定義簡化為 SPC 和 TAB 並避免不同解釋的問題其編碼包含不同實用程序的反斜杠編碼的字元。