使用grep查找包含两个字符串的目录中的所有文件

ima*_*ive 30 linux grep

我试图找出正确的语法来找到两个字符串,每个字符串的整个部分,在文件中的任何地方(不必彼此靠近)。因此,具有两者foo并说 number 的任何文件都321不必单独存在并且可以是应该匹配的子字符串。我尝试了以下方法但运气不佳:

grep 'foo\|321' *

grep 'foo|321'
Run Code Online (Sandbox Code Playgroud)

koj*_*iro 30

GNU grep

应该快一点,因为第二个grep可能对文件列表进行操作。

grep -lZ 'foo' * | xargs -0 grep -l '321'
Run Code Online (Sandbox Code Playgroud)

带查找的 POSIX grep

find如果您想搜索递归目录(在这种情况下丢失-mindepth-maxdepth选项。

find . -mindepth 1 -maxdepth 1 -type f -exec grep -q 'foo' {} \; -exec grep -l '321' {} +
Run Code Online (Sandbox Code Playgroud)

  • `-r` 在第一个 `grep` 上运行良好,使 GNU 解决方案对我来说是递归的,而不是将 POSIX 行与所有这些 `exec` 一起使用 (2认同)

小智 15

你可以用一个简短的脚本来做到这一点:

for FILE in *
do
  grep -q foo $FILE && grep -q 321 $FILE && echo $FILE
done
Run Code Online (Sandbox Code Playgroud)

您也可以在一行上执行此操作:

for FILE in *; do grep -q foo $FILE && grep -q 321 $FILE && echo $FILE; done
Run Code Online (Sandbox Code Playgroud)

grep如果找到字符串,则返回 0 (true),&&分隔命令意味着第二个命令仅在第一个为 true 时运行。该-q选项确保grep不输出任何内容。

只有在同一文件中找到两个字符串时,echo 才会运行。


我想到了一种不同的方法来做到这一点。如果有问题的文件比您安装的 RAM 大,这种方式可能会更有效,因为它只需要grep通过每个文件一次。

 for FILE in *
 do
   test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE
 done
Run Code Online (Sandbox Code Playgroud)

和单行版本:

 for FILE in *; do test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE; done
Run Code Online (Sandbox Code Playgroud)

  • @HaukeLaging `grep -q` 和 `grep -l` 不会搜索到文件末尾:一旦找到匹配项,它们就会退出。这让我想知道为什么第一个解决方案不是`for FILE in *; 做 grep -q foo "$FILE" && grep -l 321 "$FILE"; 完成` (4认同)

ghm*_*014 -1

应该

grep -e "foo" -e "321" *
Run Code Online (Sandbox Code Playgroud)

使用 -e 表示多种模式

编辑

如果您需要两者匹配:

grep -e ".*foo.*321.*" *
Run Code Online (Sandbox Code Playgroud)

如果顺序无关紧要:

grep -e ".*foo.*321.*" ".*321.*foo.*" *
Run Code Online (Sandbox Code Playgroud)

  • @HaukeLaging 因为如果任一模式匹配它就会返回。OP 正在寻找一种情况,只有在文件中找到 **both** 时才返回 true。 (2认同)