wza*_*zab 9 grep find search text
我需要找到满足相对复杂条件的文件。例如,我想找到满足以下所有条件的所有文件:
这些词可能以任何顺序出现,也可能出现在不同的行中。
我有一个解决方案,它结合了find
和egrep
,但不是很清晰。
find . \( -type f -and -exec egrep -q 'BBB|CCCCC' {} \; \
-and -exec egrep -q AAAA {} \; \
-and -not -exec egrep -q DDD {} \; \) -print
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来解决这个问题?
Qua*_*odo 15
在我看来,您的解决方案对于这项任务非常清晰。但是,它很慢,因为它为每个文件生成 3 个进程。我想在awk是更好地在这里适用,因为它将使阅读整批处理文件在一个单一的去(如由ARG_MAX允许的),使用{} +
代替{} \;
。
GNU awk:
find . -type f -exec gawk '
BEGINFILE{c1=c2=c3=0}
/AAA/ {c1=1}
/BBB/||/CCC/{c2=1}
/DDD/ {c3=1; nextfile}
ENDFILE{if(c1 && c2 && !c3)print FILENAME}
' {} +
Run Code Online (Sandbox Code Playgroud)
POSIX * :
find . -type f -exec awk '
FNR==1{
if(NR>1 && c1 && c2 && !c3)print f
c1=c2=c3=0
f=FILENAME
}
/AAA/ {c1=1}
/BBB/||/CCC/{c2=1}
/DDD/ {c3=1; nextfile}
END{if(c1 && c2 && !c3)print f}
' {} +
Run Code Online (Sandbox Code Playgroud)
*实际上,nextfile
仍然不是 POSIX 但它已被接受到下一期标准。您可以删除它以符合 POSIX 问题 7;结果将是相同的,但会有性能损失。
注意:如果 awk 没有读取文件的权限,它会退出。在 GNU Find 中,只需添加-readable
标志即可避免这种情况。如果 GNU Find 不可用,Test 可以用作附加过滤器:
find . -type f -exec test -r {} \; -exec awk '
...
' {} +
Run Code Online (Sandbox Code Playgroud)
但是为每个文件生成一个测试代表了性能损失。
进一步阅读: