检查命令输出是否在shell脚本中包含特定字符串


116

我正在编写一个shell脚本,并且试图检查命令的输出是否包含某个字符串。我以为我可能必须使用grep,但不确定如何使用。有人知道吗?


生成所需的输出字符串后,该命令是否需要继续运行,还是可以在该时间立即将其关闭?(在这方面,您的两个答案在语义上有所不同)。
查尔斯·达菲

Answers:


97

测试grep的返回值:

./somecommand | grep 'string' &> /dev/null
if [ $? == 0 ]; then
   echo "matched"
fi

习惯上是这样的:

if ./somecommand | grep -q 'string'; then
   echo "matched"
fi

并且:

./somecommand | grep -q 'string' && echo 'matched'

2
这段代码不适用于所有POSIX shell:POSIX标准只需=要是一个比较运算符,而不是==; 参见pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
Charles Duffy

4
此外,grep 'string' &>/dev/null它不仅不兼容POSIX,而且执行速度也较慢(如果string出现在较长的输出流中较早)grep -q string。[这里有一个警告,如果您要确保somecommand即使在发出之后仍然保持运行string,在这种情况下,使用grep -q-通过关闭其stdin并在string看到第一个实例后退出-会适得其反]。(Re:“非POSIX兼容”,&>是扩展-参见pubs.opengroup.org/onlinepubs/009695399/utilities/…描述了POSIX要求的重定向支持)。
查尔斯·达菲

如果已解释了为什么这样做/每个参数都起作用,将有助于理解语法,这将有所帮助
redfox05

157

测试$?是一种反模式

if ./somecommand | grep -q 'string'; then
  echo "matched"
fi

如果您只想测试固定的字符串,请添加Fx选项:grep -Fxq F表示固定(未解释),x表示整行
Erdal G. Erdal G.17

4
为什么测试的$?是反模式?
维塔利·兹达涅维奇

1
我认为@VitalyZdanevich是因为它并发性不强。
Konrad Reiche

@VitalyZdanevich,其中之一是,出于测试$?目的set -eERR陷阱的考虑,测试并未将前面的命令设置为“已检查” ,因此,在您希望程序稍后仅返回故意错误的路径的情况下,您的程序可以退出。另一个$?是不稳定的全球状态,很容易被偶然抛弃其价值。例如,如果您添加一行类似的日志echo "Exit status is $?",中的新值$?将成为的退出状态echo
查尔斯·达菲,

6

另一种选择是在命令输出上检查正则表达式匹配。

例如:

[[ "$(./somecommand)" =~ "sub string" ]] && echo "Output includes 'sub string'"

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.