GNU grep

GNU grep

我试图找出正确的语法来查找两个字符串,每个字符串的整个部分,在文件中的任何位置(不必彼此靠近)。因此,任何同时包含 numberfoo和 number 的文件321不必单独存在,并且可以是子字符串,应该匹配。我尝试了以下方法但运气不佳:

grep 'foo\|321' *

grep 'foo|321'

答案1

GNU grep

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

grep -lZ 'foo' * | xargs -0 grep -l '321'

POSIX grep 与 find

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

find . -mindepth 1 -maxdepth 1 -type f -exec grep -q 'foo' {} \; -exec grep -l '321' {} +

答案2

您可以使用一个简短的脚本来完成此操作:

for FILE in *
do
  grep -q foo $FILE && grep -q 321 $FILE && echo $FILE
done

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

for FILE in *; do grep -q foo $FILE && grep -q 321 $FILE && echo $FILE; done

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

和单行版本:

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

答案3

奇怪的。对我来说,两种变体都有效(grep (GNU grep) 2.13):

grep 'foo\|321'
grep -E 'foo|321'

编辑1- 仅显示两个匹配的文件

答案for file in *是有效的,但可能会成为性能噩梦(对于大量文件):每个文件至少有两个进程。这更快(在 GNU 世界中):

find . -type f -print0 | xargs -0 -r grep --files-with-matches --null -- string1 |
  xargs -0 -r grep --files-with-matches -- string2

string1 应该是导致较少匹配的那个。

答案4

应该

grep -e "foo" -e "321" *

使用 -e 表示多种模式

编辑

如果您需要两者匹配:

grep -e ".*foo.*321.*" *

如果顺序无关紧要:

grep -e ".*foo.*321.*" ".*321.*foo.*" *

相关内容