Bash 无过滤Grep
如何在没有实际过滤或突出显示的情况下进行grepBash 无过滤Grep,bash,shell,grep,Bash,Shell,Grep,如何在没有实际过滤或突出显示的情况下进行grep 目标是在不影响输出的情况下,找出输出中是否存在特定文本。我可以tee到一个文件,然后脱机检查该文件,但是,如果输出很大,那是浪费时间,因为它只在处理完成后处理输出: command | tee file file=`mktemp` if grep -q pattern "$file"; then echo Pattern found. fi rm "$file" 我想我也可以使用grep的before(-B)和after(-A)标志来实现实
目标是在不影响输出的情况下,找出输出中是否存在特定文本。我可以
tee
到一个文件,然后脱机检查该文件,但是,如果输出很大,那是浪费时间,因为它只在处理完成后处理输出:
command | tee file
file=`mktemp`
if grep -q pattern "$file"; then
echo Pattern found.
fi
rm "$file"
我想我也可以使用grep的before(-B
)和after(-A
)标志来实现实时处理,但如果没有匹配项,则不会输出任何内容
# Won't even work - DON'T USE.
if command | grep -A 1000000 -B 1000000 pattern; then
echo Pattern found.
fi
有没有更好的方法来实现这一点?类似于“假装正在grep并设置退出代码,但不要grep任何东西”
(实际上,我将要做的是管道stderr,因为我正在寻找某个错误,所以我将使用
command |…
而不是command 2>>(…>&2;result=${PIPESTATUS[*]})
,这实现了同样的效果,只是它在stderr上工作。)要允许输出搜索结果,您可以使用awk:
command | awk '/pattern/{print "Pattern found"} 1'
当模式
在任何行中匹配时,这将打印“找到的模式”。(行将稍后打印)
如果要在打印前打印行,请使用:
command | awk '{print} /pattern/{print "Pattern found"}'
编辑:要在匹配时执行任何命令,请使用:
command | awk '/pattern/{system("some_command")} 1'
编辑2:要处理关键字中的特殊字符,请使用以下命令:
command | awk -v search="abc*foo?bar" 'index($0, search) {system("some_command"); exit} 1'
我认为您希望打印输出的每一行,但同时跟踪是否找到特定的模式。只需将输出传递到
sed
或grep
就会影响输出。您需要这样做:
pattern=0
command | while read line
do
echo "$line"
if grep -q "$pattern" <<< "$lines"
then
((pattern+=1))
fi
done
if [[ $pattern -gt 0 ]]
then
echo "Pattern was found $pattern times in the output"
else
echo "Didn't find the pattern at all"
fi
请注意2>&1
。这意味着获取STDERR(即文件描述符2)并将其重定向到STDOUT(文件描述符1)。现在,这两个都将在读取时通过管道传输到循环中
grep-q
将阻止grep
将其输出打印到STDOUT。它将打印到STDERR,但在本例中这不应该是一个问题。Grep仅在无法打开请求的文件或缺少模式时打印STDERR。如果您只想在找到模式时设置退出代码,那么这应该可以做到:
awk -v rc=1 '/pattern/ { rc=0 } 1; END {exit rc}'
-v rc=1
在Awk程序内创建一个名为rc
(简称“返回代码”)的变量,并将其初始化为值1。节/pattern/{rc=0}
使得每当遇到与正则表达式pattern
匹配的行时,该变量被设置为0。1代码>是一个始终为真的条件,没有附加任何操作,这意味着默认操作将在每一行上执行;默认操作是打印出该行,因此此筛选器将原封不动地将其输入复制到输出。最后,END{exit rc}
在没有更多的输入要处理时运行,并确保awk
以rc
变量的值作为其进程退出状态终止:如果找到匹配项,则为0,否则为1
shell将退出代码0解释为true,将非零解释为false,因此此命令适合用作shellif
或while
语句的条件,可能位于管道的末尾。您可以执行以下操作:
echo "'search string' appeared $(command |& tee /dev/stderr | grep 'search string' | wc -l) times"
这将打印命令
的整个输出,后跟以下行:
'search string' appeared xxx times
技巧在于,tee
命令不用于将副本推入文件,而是用于将stdout
中的所有内容复制到stderr
。由于未连接到管道,stderr
流会立即显示在屏幕上,而stdout
上的副本会被grep
/wc
组合所吞噬
由于错误消息通常会被发送到stderr
,并且您说过要对错误消息进行grep,因此第一个管道使用|&
操作符将命令的stderr
组合到其stdout
,并将两者都推入tee
命令中。尝试此脚本。当找到模式时,它不会修改您的命令的任何输出
和sed以0退出,否则为1。从我对你的问题和评论的理解来看,我想这是你想要的
if your-command | sed -nr -e '/pattern/h;p' -e '${x;/^.+$/ q0;/^.+$/ !q1}'; then
echo Pattern found.
fi
下面是一些测试用例:
ubuntu-user:~$ if echo patt | sed -nr -e '/pattern/h;p' -e '${x;/^.+$/ q0;/^.+$/ !q1}'; then echo Pattern found.; fi
patt
ubuntu-user:~$ if echo pattern | sed -nr -e '/pattern/h;p' -e '${x;/^.+$/ q0;/^.+$/ !q1}'; then echo Pattern found.; fi
pattern
Pattern found.
注意:当您的命令没有输出时,前面的脚本无法工作,因为sed不会一直运行sed表达式并以0退出。我不想抑制任何命令的输出。您可以实现您想要的,但问题是,只要grep
找到匹配项,命令也会被终止,在保留输出时没有任何用处(因为命令在两者之间被停止)。你能解释一下你要达到的目标是什么吗?目标是找出某个程序是否输出了某个错误。我希望在错误发生时也将其打印到终端,因为错误可能取决于stdin上输出的上下文,将所有错误缓存到文件中并仅在最后回显会破坏这种关系。我想知道输出是否包含某个字符串,不以任何方式修改输出。是的,我知道,这就是这个awk所做的,除了添加一个“Pattern found”
行之外,它根本不会更改输出,因为我不希望添加任何行,而是希望在找到行时执行代码,我如何使用awk实现这一点?我想最坏的情况是我能让它把信号写入文件吗?(难看)awkprint“Pattern found”
中的那一行可以更改为使用system
function.1+,很好地使用了awk
。你能解释一下awk'/pattern/{system(“some_命令”)}1中的1
是如何打印所有输入行的。stdout和stderr会像运行命令时通常那样进行交错打印吗?@MihaiDanila Interleave where?你说的是格雷普吗?这个
ubuntu-user:~$ if echo patt | sed -nr -e '/pattern/h;p' -e '${x;/^.+$/ q0;/^.+$/ !q1}'; then echo Pattern found.; fi
patt
ubuntu-user:~$ if echo pattern | sed -nr -e '/pattern/h;p' -e '${x;/^.+$/ q0;/^.+$/ !q1}'; then echo Pattern found.; fi
pattern
Pattern found.