grep两种不同字符串的不同方法,在同一文件中以任何顺序或行出现

时间:2018-05-24 09:32:54

标签: bash grep

我想要返回所有包含字符串的文件:"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'

2 个答案:

答案 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用作行分隔符,有效地诋毁整个文件