检查命令的输出是否包含 shell 脚本中的某个字符串

我正在编写一个 shell 脚本,并尝试检查命令的输出是否包含某个字符串。我想我可能得用 grep 但我不知道怎么用。有人知道吗?

255153 次浏览

测试 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'

测试 $?反模式。

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

另一个选项是检查命令输出上的正则表达式匹配。

例如:

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

一个干净的 if/else 条件 shell 脚本:

if (ls | grep '$1')
then
echo "exists"
else
echo "doesn't exist"
fi

简短的回答

以上所有(非常优秀的)答案都假设 grep可以“看到”命令的输出,这并不总是正确的:

SUCCESS 可以发送到 < strong > STDOUT ,而 失败可以发送到 STDERR

因此,取决于您测试的方向,您的 grep可能会失败。也就是说,如果您正在测试 失败的情况,那么在这种情况下,您必须使用 2>&1将命令的输出重定向到 STDOUT。

更长的回答

我使用 grep在 bash 脚本中进行了一个我认为非常简单的测试,结果一直失败。接着就是很多挠头的事情。使用 set -x在我的脚本显示,变量是空的!因此,我创建了以下测试来了解事情是如何破裂的。

注意 : iscsiadm是来自“ < strong > open-iscsi ”包的 Linux 工具,用于连接/断开主机到 SAN 存储。命令 iscsiadm -m session用于显示是否建立了任何 LUN 连接) :

#!/bin/bash


set -x


TEST1=$(iscsiadm -m session)
TEST2=$(iscsiadm -m session 2>&1)
echo
echo 'Print TEST1'
echo $TEST1
echo
echo 'Print TEST2'
echo $TEST2
echo

如果连接了 LUN 曾经是,则两个变量都成功地填充了值:

Print TEST1
tcp: [25] 192.168.X.XX:3260,1 iqn.2000-01.com.synology:ipdisk.Target-LUN1 (non-flash) tcp: [26] 192.168.X.XX:3260,1 iqn.2000-01.com.synology:storagehost.Target-LUN1 (non-flash)


Print TEST2
tcp: [25] 192.168.X.XX:3260,1 iqn.2000-01.com.synology:ipdisk.Target-LUN1 (non-flash) tcp: [26] 192.168.X.XX:3260,1 iqn.2000-01.com.synology:storagehost.Target-LUN1 (non-flash)

然而,如果一个 LUN abc2连接上了,abc0就会把输出发送到 STDERR,而且只有“ 测试2”变量被填充到我们使用 2>&1重定向到 STDOUT 的地方,而没有重定向到 STDOUT 的“ 测试1”变量是空的:

iscsiadm: No active sessions.


Print TEST1




Print TEST2
iscsiadm: No active sessions.

结论

如果您遇到类似这样的时髦的、半破碎的 只能朝一个方向工作,而不能朝另一个方向情况,请尝试使用您自己的命令替换 iscsiadm,您应该获得适当的可见性来重写测试以正确工作。