unix 查找包含多个字符串的文件

kwvwclae  于 2022-11-04  发布在  Unix
关注(0)|答案(6)|浏览(190)

我使用一个命令来递归查找包含特定string1的文件:

find . -type f -exec grep -H string1 {} \;

我需要找到包含多个字符串的文件,所以命令应该返回那些包含所有字符串的文件。

find . -type f -exec grep -H string1 AND string2 {} \;

我找不到方法。字符串可以在文件中的任何地方。即使只有两个字符串的解决方案也会很好。

anhgbhbe

anhgbhbe1#

您还可以尝试以下操作;

find . -type f -exec grep -l 'string1' {} \; | xargs grep -l 'string2'

这将显示包含string 1和string 2的文件名

ulydmbyx

ulydmbyx2#

您可以链接您的操作,并使用第一个操作的退出状态,以便仅在第一个操作成功时执行第二个操作。(省略主操作之间的运算符默认为-and/-a。)

find . -type f -exec grep -q 'string1' {} \; -exec grep -H 'string2' {} \;

第一个grep命令使用-q“quiet”,如果找到该字符串,它将返回成功退出状态。
要收集包含string1的所有文件,然后仅通过一次grep调用来搜索string2,可以使用-exec ... {} +

find . -type f -exec grep -q 'string1' {} \; -exec grep 'string2' {} +
cbjzeqam

cbjzeqam3#

使用GNU grep

grep -rlZ 'string1' | xargs -0 grep -l 'string2'

man grep开始
-r,--递归
递归地读取每个目录下的所有文件,如果符号链接在命令行中,则遵循这些符号链接。注意,如果没有给定文件操作数,grep将搜索工作目录。这等效于-d递归选项。
-Z,--null输出零字节(ASCII NUL字符),而不是通常跟在文件名后面的字符。例如,grep -lZ在每个文件名后面输出一个零字节,而不是通常的换行符。此选项使输出明确,即使文件名包含换行符等不常见字符。此选项可与find -print 0、perl-0、sort -z和xargs -0来处理任意文件名,甚至是包含换行符的文件名。

pzfprimi

pzfprimi4#

令人惊讶的是,这个老问题缺少显而易见的简单的Awk解决方案:

find . -type f -exec awk '/string1/ && /string2/ { print; r=1 } END { exit 1-r }' {} \;

使用r变量的技巧只是模拟grep中的退出代码(0表示找到,1表示没有;如果你不在乎,你可以把它拿出来)。
为了提高效率,可以从-exec ... {} \;切换到-exec ... {} +,不过您可能需要对Awk脚本进行一些重构(或者丢弃退出代码,或者更改退出代码,使退出代码指示“no files matched”与“only some files matched”与“all files matched”?)
上面的代码查找在同一行中包含两个字符串的文件。在任何行中查找它们的情况是很容易改变的。

awk '/string1/ { s1=1 }
  /string2/ { s2=1 }
  s1 && s2 { print FILENAME; exit }
  END { exit(1 - (s1 && s2)) }' file

这只是打印文件名,并且假设您只有一个输入文件。要处理多个文件,请稍微重构,以便在访问新文件时重置s1s2的值:

awk 'FNR == 1 { s1 = s2 = 0 }
  /string1/ { s1 = 1 }
  /string2/ { s2 = 1 }
  s1 && s2 { r=1; print FILENAME; nextfile }
  END { exit 1-r }' file1 file2 file3 ...

一些古老的Awk版本可能不支持nextfile,尽管它现在在POSIX中。

whlutmcx

whlutmcx5#

答案
正如您在本页的其他答案中所看到的,有几个命令行工具可用于执行跨文件的联合搜索。一个尚未发布的快速而灵活的解决方案是使用ag

ag -l string1 | xargs ag -l string2

有用的变化

对于不区分大小写的搜索,请使用ag-i选项:

ag -il string1 | xargs ag -il string2

对于其他搜索词,请扩展管道:

ag -l string1 | xargs ag -l string2 | xargs ag -l string3 | xargs ag -l string4
o8x7eapl

o8x7eapl6#

grep -rlZ string1 | xargs -0 grep -l string2

如果您的模式是固定字符串,我们可以通过在grep中添加-F来加快命令的执行速度:

grep -rlZF string1 | xargs -0 grep -lF string2

相关问题