我正在编写一个简单的脚本,用于检查命令输出中的某个关键字。为了查看它是否有效,我从 bash 命令行检查了该命令。
$ ls | grep -q foo
$ echo $?
它显示 1 或 0,具体取决于命令输出和预期的 grep 参数。
我厌倦了重新输入命令,所以我| echo $?
在命令行末尾添加了。
$ ls | grep -q foo | echo $?
然后,无论命令输出如何,它总是返回 0,即使第一部分应该返回 1。
我猜这是正常行为,但我想知道为什么 bash 以这种方式工作。
答案1
这是因为管道采用标准输出并将其通过管道传输到下一个命令,而您想要的是分号。
ls | grep -q foo; echo $?
这样就完成了ls
和grep
命令,然后执行echo
命令。
答案2
$ ls | grep -q foo | echo $?
然后,无论命令输出如何,它总是返回 0,即使第一部分应该返回 1。
更准确地说,echo $?
此管道中的将打印管道之前执行的前一个命令的退出代码。在此示例中,它将输出 7:
( exit 7 )
ls / | grep . | echo $?
ls | grep -q foo | echo $?
在命令行上输入并按下回车键后,将会发生以下事情(其中包括):
- shell 解析并解释命令行。
$?
它用您按下回车键之前执行的前一个命令的退出代码替换变量。- 例如,如果前一个命令以 7 退出,则 shell 认为要执行的命令是
ls | grep -q foo | echo 7
- 它执行该命令。
换句话说,当您按下 Enter 键执行管道时ls | grep -q foo | echo $?
,shell 会解析并解释它收到的行,并$?
在开始执行管道中的命令之前评估变量。
相关说明一下,您可以在条件语句中直接使用退出代码,例如:
if ls | grep -q foo; then echo success, there is foo; fi
或者,如果您想在成功时执行某些操作,则可以使用以下命令链接下一个命令&&
:
ls | grep -q foo && echo success