我尝试读取用户输入并将其与存储值进行比较,如下所示:
read confirm
if [ echo $confirm | grep -q y ]; then
...
fi
但是,这会导致一对错误:
[: missing `]'
grep: ]: No such file or directory
为什么会发生这种情况,以及适当的选择是什么?
答案 0 :(得分:4)
对于您的直接用例,您只需要:
if echo "$confirm" | grep -q y; then
...或其效率更高的等价物(如果你的shell是bash):
if [[ $confirm = *y* ]]; then
...或更有效的等价物(对于任何 POSIX shell):
case $confirm in *y*) echo "Put your code for the yes branch here" ;; esac
[
不是if
语法的一部分:if
只是在then
之前将(可能是复合的)命令作为其参数。 [
是test
命令的不同名称,它对其参数运行检查;但是,如果您要测试的是grep -q
的退出状态,则根本不需要为此调用test
命令。
如果在|
命令中放置[
,则会使复合命令成为管道,并启动一个新的简单命令。因此|
之后的参数不再传递给[
。
使用原始代码:
if [ echo $confirm | grep -q y ]; then
...这是在运行两个命令,它们之间有一个管道:
[ echo $confirm # first command
grep -q y ] # second command
由于[
要求其最后一个参数为]
,因此它报告缺少该强制参数;由于grep
将额外的参数视为要读取的文件名,因此它抱怨没有找到名为]
的文件。
此外,[ "$foo" ]
检查foo
的内容是否为空。由于grep -q
的输出总是为空,[ "$(echo "$confirm" | grep -q y)" ]
虽然在语法上正确,但总是会评估为false,即使{{>>退出状态 {{ 1}}更改以指示是否找到匹配项。 (grep -q
相反,是一种可以发出正确结果的替代方法 - 使用[ "$(echo "$confirm" | grep y)" ]
来测试[ ]
的输出是否为空 - 但效率低于最佳实践方法)。
grep
语法来自if
:
help if
执行
if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
列表。如果它的退出状态为零,那么if COMMANDS
列表已执行。否则,每个then COMMANDS
列表都是 依次执行,如果其退出状态为零,则对应 执行elif COMMANDS
列表,if命令完成。除此以外, 执行then COMMANDS
列表(如果存在)。退出状态 整个构造是最后执行的命令的退出状态,或者为零 如果没有条件测试成真。
值得注意的是,else COMMANDS
采用了一系列命令,语法规范中不包含if
。