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

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

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

例子:

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 正则表达式的优势。

相关内容