我正在基于正则表达式搜索文件,然后尝试搜索这些文件的内容。所以,举例来说,我有类似的东西
#Find all C++ files that match a certain pattern and then search them
find . -name "*.cpp" | grep "<name regex>" | xargs grep "<content regex>"
我遇到的问题是某些路径中有空格,这让xargs
.我知道,如果我只是使用find
,我可以使用-print0
参数(以及-0
上的参数xargs
)来防止 xargs 将空格视为分隔符。有类似的东西吗grep
?
或者我完全以错误的方式处理这个问题?天真地,find
to grep
toxargs grep
对我来说是有意义的,但我对产生相同结果的其他方法持开放态度。
答案1
也许使用类似的东西(如果是 gnu grep)。
grep -r 'content pattern' --include==*.cpp
人 grep
--include=GLOB 仅搜索基本名称与 GLOB 匹配的文件(使用 --exclude 中所述的通配符匹配)
另请参阅空分隔符的选项。
-Z, --null 输出零字节(ASCII NUL 字符),而不是通常跟在文件名后面的字符。例如,grep -lZ 在每个文件名后输出一个零字节,而不是通常的换行符。即使文件名包含换行符等不常见字符,此选项也会使输出明确无误。此选项可以与 find -print0、perl -0、sort -z 和 xargs -0 等命令一起使用来处理任意文件名,甚至是包含换行符的文件名。
-z, --null-data 将输入视为一组行,每行以零字节(ASCII NUL 字符)而不是换行符结尾。与 -Z 或 --null 选项一样,此选项可以与 sort -z 等命令一起使用来处理任意文件名。
答案2
如果你必须跳过很多圈,那么 xargs 的效率无论如何都会损失。这是一种粗略的解决方法:
find . -iname "*.cpp" | grep "<pattern>" | while read -r x; do grep exa "$x"; done
每次我遇到文件名中的空格问题时,答案都是变量上的双引号。
答案3
用于find
执行所有文件名过滤。而不是
find . -name "*.cpp" | grep "foo" | xargs grep …
做
find . -name "*.cpp" -name "*foo*" -print0 | xargs -0 grep …
如果你想做一些稍微复杂的事情,比如
find . -name "*.cpp" | egrep "foo|bar" | xargs grep …
你可以做
find . -name "*.cpp" "(" -name "*foo*" -o -name "*bar*" ")" -print0 | xargs -0 grep …
请注意,即使对于具有以下内容的文件,这些也应该适用换行符以他们的名义。
而且,如果您需要成熟的正则表达式的强大功能,您可以使用-regex
.
答案4
即使没有 GNU 工具,这也应该可以工作:
#Find all C++ files that match a certain pattern and then search them
find . -name "*.cpp" | grep "<name regex>" | perl -pe 's/\n/\0/' \
| xargs -0 grep "<content regex>"
该perl
调用用空字符替换换行符,这将允许xargs -0
按行而不是按空格解释输入。
使用 GNU,您可以删除该perl
调用并更改xargs -0 …
为xargs -d "\n" …
没有perl
GNU?试试awk '{printf "%s%c", $0, 0}'
吧。