几天前我开始学习 Bash。
我正在尝试将表达式的退出状态获取grep
到变量中,如下所示:
check=grep -ci 'text' file.sh
我得到的输出是
No command '-ic' found
我应该使用管道命令来执行此操作吗?
答案1
你的命令,
check=grep -ci 'text' file.sh
将被 shell 解释为“-ci
使用参数text
和运行命令file.sh
,并将变量设置为其环境中的check
值”。grep
shell 将最近执行的命令的退出值存储在变量中?
。您可以将其值分配给您自己的变量之一,如下所示:
grep -i 'PATTERN' file
check=$?
如果你想根据这个值采取行动,你可以使用你的check
变量:
if [ "$check" -eq 0 ]; then
# do things for success
else
# do other things for failure
fi
或者您可以跳过使用单独的变量并必须$?
一起检查:
if grep -q -i 'pattern' file; then
# do things (pattern was found)
else
# do other things (pattern was not found)
fi
(请注意-q
,它指示grep
不输出任何内容并在匹配时立即退出;我们对这里的匹配内容并不真正感兴趣)
或者,如果您只想在模式出现时“做事”不是成立:
if ! grep -q -i 'pattern' file; then
# do things (pattern was not found)
fi
$?
仅当您稍后需要使用它时,当 in 中的值$?
已被覆盖时,才需要保存到另一个变量中,如
mkdir "$dir"
err=$?
if [ "$err" -ne 0 ] && [ ! -d "$dir" ]; then
printf 'Error creating %s (error code %d)\n' "$dir" "$err" >&2
exit "$err"
fi
在上面的代码片段中,$?
将被测试结果覆盖[ "$err" -ne 0 ] && [ ! -d "$dir" ]
。仅当我们需要显示它并将其与 一起使用时才需要将其保存在这里exit
。
答案2
check=grep
您已告诉 bash在传递给命令的环境中设置变量
-ci 'text' file.sh
但ci
不存在。
我相信您的意思是将该命令括在反引号中,或者放在前面有美元符号的括号中,其中任何一个都会分配在文件中找到“文本”的行数(不区分大小写):
check=`grep -ci 'text' file.sh`
check=$(grep -ci 'text' file.sh)
如果没有匹配,现在$check
应该为 0,如果有任何匹配,则应该为正。
答案3
您的问题不清楚,但根据您提交的代码,您似乎希望变量check
存储grep
命令的退出状态。执行此操作的方法是运行
grep -ci 'text' file.sh
check=$?
从 shell 运行命令时,可以通过特殊的 shell 参数 来获取其退出状态$?
。
POSIX(类 Unix 操作系统的标准)在其文档中记录了这一点外壳规格Bash 的实现记录在特殊参数。
由于您是新学习者,我强烈建议您从一本好书和/或在线教程开始学习基础知识。 Stack Exchange 网站上不鼓励推荐外部资源,但我建议Lhunath 和 GreyCat 的 Bash 指南。
答案4
其他答案阐明了您的命令不起作用的原因,以及有关如何测试其结果的一些很好的建议。我想再补充一点。
$(命令)$?附加退出代码
您可以使用命令替换和退出代码检查的组合来完成此操作,全部在一行中完成。它将把退出代码作为数字附加到输出中。
check=$( grep -ci 'text' file.sh )$?
这实际上是$(some command)
(获取命令的字符串输出)紧随其后的是$?
(获取最后一个命令的退出代码)。为了工作,它们必须一起使用,没有空间。
如果有任何输出的可能性(大多数命令都是这种情况),则必须使用 抑制它> /dev/null 2>&1
。
如果您使用诸如 之类的测试命令,这可能不是必需的test -d <directory>
。
check=$( grep -ci 'text' file.sh > /dev/null 2>&1)$?
您可以使用一个函数来抽象它:
e() {
$@ > /dev/null 2>&1
}
# Usage:
check=$(e grep -ci 'text' file.sh)$?
测试退出代码
要稍后使用它,请针对零进行测试(成功):
[ $check -eq 0 ] && echo "passed" || echo "didn't pass"
[ $check -ne 0 ] && echo "didn't pass" || echo "passed"
使用 if/then/else 结构,针对零进行测试(成功):
if [ $check -eq 0 ]; then
echo "passed"
else
echo "didn't pass"
fi
if [ $check -ne 0 ]; then
echo "didn't pass"
else
echo "passed"
fi
直接测试退出代码
在子 shellexit
中使用将根据您可以直接使用的数字生成正确的退出代码:(
)
(exit $check) && echo "check passed" || echo "check didn't pass"
! (exit $check) && echo "check didn't pass" || echo "check passed"
使用 if/then/else 结构,直接使用退出代码:
if (exit $check); then
echo "passed"
else
echo "didn't pass"
fi
if ! (exit $check); then
echo "didn't pass"
else
echo "passed"
fi
使用return
代替exit
也可以在某些 shell 中工作 - 包括 zsh(但不是 bash)。
变得花哨
如果您想进一步简化,请使用此函数:
t() { return $1; }
现在你可以这样测试:
t $check && echo "passed" || echo "didn't pass"
! t $check && echo "didn't pass" || echo "passed"