我想要返回所有包含字符串的文件:"main("
以及"foo"
。
这就像使用多模式OR grep但使用AND代替。
我提出的最好的是:
grep -rl . -e "main("|while read fname; do grep -rl "$fname" -e "foo"; done
它完成了这项工作,但理想情况下我不必编写bash脚本。
E.g。
text1.txt:
int main()
{
stuff....
}
foo
grep命令会返回text1.txt,因为它包含字符串' main('和' foo'
答案 0 :(得分:2)
只需使用awk匹配模式和打印文件名:
awk 'FNR == 1 { m = f = 0 } # reset flags at start of each file
/main\(/ { ++m } /foo/ { ++f } # set flags when patterns match
m && f { print FILENAME; nextfile }' **/*
nextfile
是一个GNU扩展,跳转到下一个文件,而不是下一行。启用globstar
后,**
会递归扩展。在交互式bash shell中,默认情况下会启用它,但在脚本中,您可以使用shopt -s globstar
自行启用它。
使用非GNU awk,您可以使用另一个标记跳过行并避免多次打印文件名:
awk 'FNR == 1 { m = f = p = 0 } # reset flags at start of each file
p { next } # skip lines once this filename has been printed
/main\(/ { ++m } /foo/ { ++f }
m && f { print FILENAME; ++p }' **/*
答案 1 :(得分:1)
尝试
grep -rlZ 'main(' | xargs -0 grep -l 'foo'
-Z, - 空 输出零字节(ASCII NUL字符),而不是通常在文件后面的字符 名称。例如,grep -lZ在每个文件名后输出一个零字节,而不是通常的换行符。 即使存在包含异常的文件名,此选项也会使输出明确无误 像换行符这样的字符。此选项可用于find -print0,perl -0,sort -z等命令, 和 xargs -0 来处理任意文件名,甚至包含换行符的文件名。
第一个grep
将打印包含{N}字符分隔的main(
的所有文件名。然后xargs
会将文件传递给第二个grep
命令,该命令会打印包含foo
的文件
如果文件足够小并且不包含NUL字符,
grep -rlz 'main(.*foo\|foo.*main('
其中-z
将NUL用作行分隔符,有效地诋毁整个文件