grep二次过滤显示(standard input)而非文件名的问题及方案验证
问题解析与解决方案
为什么第二次grep会显示(standard input)
当grep直接读取本地文件时,-H参数会输出对应的文件名;但如果grep是通过管道接收前一个命令的输出(即从标准输入读取内容),-H会把输入源标记为(standard input)(你的示例里是德语本地化后的Standardeingabe)。你第二次执行grep -vH "34"时,输入来自前一个grep的管道输出,而非直接读取文件,因此会出现这个前缀。
你用的xargs -0方案是否合理?
不合理,属于巧合生效:
xargs -0的设计目的是处理以null字符分隔的输入(通常配合find -print0使用,避免文件名含空格、换行等特殊字符时出错)。但前一个grep的输出是换行分隔的匹配行,没有null字符,xargs -0无法正确分割输入,会把所有行当成一个整体处理。最终能得到正确结果只是因为输出行结构没有被破坏,一旦行内包含空白字符,这个命令就会出错。
正确的解决方案
方案1:去掉第二个grep的-H参数
直接通过管道过滤,利用第一个grep已经在每行开头包含文件名的特性:
find /home/tom/tmp/test_grep -name "*.log" -type f | xargs grep -i ERROR | grep -v "34"
执行后会直接输出符合要求的行,不会出现(standard input)前缀。
方案2:用find的exec减少管道次数
在每个文件内部完成两次过滤,效率更高:
find /home/tom/tmp/test_grep -name "*.log" -type f -exec sh -c 'grep -i ERROR "$1" | grep -v "34"' _ {} \;
方案3:单grep命令实现复合过滤(正则方式)
用正则表达式同时匹配含ERROR且不含34的行,无需管道:
find /home/tom/tmp/test_grep -name "*.log" -type f | xargs grep -i 'ERROR:[^;]*[^34]'
注:该正则针对你示例中的日志格式(ERROR:xxx)调整,若日志格式不同,可根据实际结构修改正则规则。
内容的提问来源于stack exchange,提问作者falcon68
相关产品推荐
相关产品推荐

