我正在编写一个 shell 脚本,我正在尝试检查命令的输出是否包含某个字符串。我想我可能必须使用 grep,但我不确定如何。有人知道吗?
5 回答
测试$?
是一种反模式。
if ./somecommand | grep -q 'string'; then
echo "matched"
fi
测试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'
另一种选择是检查命令输出上的正则表达式匹配。
例如:
[[ "$(./somecommand)" =~ "sub string" ]] && echo "Output includes 'sub string'"
一个干净的 if/else 条件 shell 脚本:
if ./somecommand | grep -q 'some_string'; then
echo "exists"
else
echo "doesn't exist"
fi
简短的回答
以上所有(非常优秀的)答案都假设grep
可以“看到”命令的输出,这并不总是正确的:
SUCCESS可以发送到STDOUT,而FAILURE可以发送到STDERR。
因此,根据您测试的方向,您grep
可能会失败。也就是说,如果您正在测试FAILURE2>&1
的情况,则必须在这种情况下使用将命令的输出重定向到 STDOUT 。
带证明的更长答案
我在 bash 脚本中使用了我认为非常简单的测试,grep
但它一直失败。随之而来的是许多挠头。在我的脚本中使用set -x
发现变量是空的!所以我创建了以下测试来了解事情是如何破坏的。
注意:iscsiadm
是“ 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未连接,iscsiadm
则将输出发送到 STDERR,并且只有“ TEST2 ”变量填充了我们使用2>&1
;重定向到 STDOUT 的位置。没有重定向到 STDOUT 的“ TEST1 ”变量为空:
iscsiadm: No active sessions.
Print TEST1
Print TEST2
iscsiadm: No active sessions.
结论
如果你有一个时髦的、半损坏的——在一个方向上工作但在另一个方向上没有——像这样的情况,试着iscsiadm
用你自己的命令替换上面的测试,你应该得到适当的可见性来重写你的测试以使其正常工作。