grep 具有模式 A 的文件,但排除具有模式 B 的文件

grep 具有模式 A 的文件,但排除具有模式 B 的文件

我想要 grep 包含模式 A (iwant) 的文件,但我想排除包含模式 B (idontwant) 的文件。

例子:

read -p "...what are you looking for: " iwant
read -p "...what should not be included: " idontwant

iwant="blue car" 
idontwant="red car"

假設我有以下文件:

-rw-rw-r--.  1 terpentin terpentin  45 Jun  8 16:04 blue.car
-rw-rw-r--.  1 terpentin terpentin  44 Jun  8 16:05 mixed.car
-rw-rw-r--.  1 terpentin terpentin  40 Jun  8 16:04 red.car
find . -type f -print -exec cat {} \;

./mixed.car
blue car
red car
blue car

./red.car
red car
red car
red car

./blue.car
blue car
blue car
blue car

怎麼可能只得到文件“./blue.car”作為結果?

原始內容包括數百個長文本文件,因此盡可能節約資源非常重要。

答案1

使用

find . -type f ! -exec grep -q "$idontwant" {} ';' -exec grep -q "$iwant" {} ';' -print

或者

find . -type f -exec grep -q "$iwant" {} ';' ! -exec grep -q "$idontwant" {} ';' -print
  • 命令中的術語(有時稱為“謂詞”)find 的特徵為測試(例如,  -type f)和行動(例如, -print和 -delete)。從手冊頁可能很難弄清楚-exec兩者都是 行動和一個 測試。所以,正如
    尋找 。 -type f -mtime -30 -name '*.txt' -可讀 -size +5測試6 測試7 測試8……
    連續將搜尋範圍縮小到滿足所有條件的檔案(滿足所有指定的測試),因此
    尋找 。 -執行命令1{} ';' -執行命令2{} ';' -執行命令3{} ';' ……
    尋找所有指令都成功的檔案。
  • 任何find測試都可以透過在其前面加上 來否定(反轉)!。因此find . ! -type d可以找到普通檔案、符號連結、命名管道、套接字和裝置檔案——除了目錄之外的所有檔案。
  • 請注意,! -exec grep …不等於-exec grep -v …。  -exec grep -v …將找到至少有一行不符的文件。  ! -exec grep …會在哪裡找到文件線條匹配。
  • 選項-qtogrep是 的正式同義詞--quiet,但它也意味著快的。它不會寫入任何輸出(可能除了錯誤訊息(如果適用)),一旦找到匹配項它就會退出 - 它不會讀取每個文件到末尾來查找每一個匹配。 (當然,如果文件不包含任何匹配項,則grep必須完整讀取它才能確定。)
  • 所以 (長話短說)命令查找其文件
    grep -q“$iwant”     文件
    成功並且
    grep -q“$idontwant”文件
    失敗(因為我們在它前面加上了!)。
  • 這兩個命令在功能上是等效的,但可能具有不同的效能(即,可能需要不同的運行時間)。如果只有幾個檔案包含搜尋字串,
    尋找 。 -type f -exec grep -q "$iwant" {} ';' ! -exec grep -q "$idontwant" {} ';' -列印
    會更快,因為這grep "$iwant"會消除大部分文件。如果許多文件都包含這兩個字串,則
    尋找 。 -輸入f! -exec grep -q "$idontwant" {} ';' -exec grep -q "$iwant" {} ';' -列印
    會更快,因為這! grep "$idontwant"會消除大部分文件。

答案2

我們可以透過GNU grep明智地選擇 regex 和 grep 選項來執行檔案名稱提取:

$ grep -lzPsr '(?s:(?=.*blue)(?!.*red))' .

我們在 slurp 模式 (-z) 下運行 grep,其中整個檔案被視為一大行。

-l 將列出與正規表示式相符的檔案的檔案名稱。

-r 將在目前目錄下的所有檔案上遞歸運行。

-s 將使 grep 靜默,不發出任何警告。

正規表示式將查找文件中是否存在藍色且不存在紅色,以便回答「是」。

-P 在 grep 中呼叫 Perl 正規表示式引擎,以便我們可以利用 pcre 正規表示式的優勢。

相關內容