我试图找出正确的语法来查找两个字符串,每个字符串的整个部分,在文件中的任何位置(不必彼此靠近)。因此,任何同时包含 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.*" *