【发布时间】:2012-02-16 11:07:12
【问题描述】:
灵感来自this question:
当条件是命令替换且命令不产生输出时,if 语句应该做什么?
注意:示例是if $(true); then ...,而不是if true ; then ...
例如,给定:
if $(true) ; then echo yes ; else echo no ; fi
我认为$(true) 应该替换为true 命令的输出,这没什么。然后它应该等同于:
if "" ; then echo yes ; else echo no ; fi
打印no,因为没有名称是空字符串的命令,或者到这个:
if ; then echo yes ; else echo no ; fi
这是一个语法错误。
但实验表明,如果命令没有输出,if 语句会根据命令的状态而不是输出将其视为真或假。
这是一个演示该行为的脚本:
#!/bin/bash
echo -n 'true: ' ; if true ; then echo yes ; else echo no ; fi
echo -n 'false: ' ; if false ; then echo yes ; else echo no ; fi
echo -n '$(echo true): ' ; if $(echo true) ; then echo yes ; else echo no ; fi
echo -n '$(echo false): ' ; if $(echo false) ; then echo yes ; else echo no ; fi
echo -n '$(true): ' ; if $(true) ; then echo yes ; else echo no ; fi
echo -n '$(false): ' ; if $(false) ; then echo yes ; else echo no ; fi
echo -n '"": ' ; if "" ; then echo yes ; else echo no ; fi
echo -n '(nothing): ' ; if ; then echo yes ; else echo no ; fi
这是我得到的输出(Ubuntu 11.04,bash 4.2.8):
true: yes
false: no
$(echo true): yes
$(echo false): no
$(true): yes
$(false): no
"": ./foo.bash: line 9: : command not found
no
./foo.bash: line 10: syntax error near unexpected token `;'
./foo.bash: line 10: `echo -n '(nothing): ' ; if ; then echo yes ; else echo no ; fi'
前四行的行为符合我的预期; $(true) 和 $(false) 行令人惊讶。
进一步的实验(此处未显示)表明,如果$( 和) 之间的命令产生输出,则其退出状态不会影响if 的行为。
我看到 bash、ksh、zsh、ash 和 dash 的行为相似(但在某些情况下出现不同的错误消息)。
我在 bash 文档或 POSIX“Shell 命令语言”规范中没有看到任何解释这一点的内容。
(或者我可能遗漏了一些明显的东西。)
编辑:根据接受的答案,这是另一个行为示例:
command='' ; if $command ; then echo yes ; else echo no ; fi
或者,等效地:
command= ; if $command ; then echo yes ; else echo no ; fi
【问题讨论】:
-
这很有趣。无论如何,我认为你的问题有错误。您说
if "" ; then echo yes ; else echo no ; fi返回 no 因为“没有名称为空字符串的命令”,但按照同样的逻辑,它应该会失败,并出现类似“: command not found”的错误。 if "" ; then echo yes ; else echo no ; fi和if "nonexistant" ; then echo yes ; else echo no ; fi之间还有一些其他区别 -
@AaronMcDaid:我认为您的评论有误。
if "nonexistent" ; then …产生错误消息bash: nonexistent: command not found,然后是no。相比之下,if "" ; then …产生错误消息bash: : command not found,然后是no。这是完全相同的行为,除了nonexistent已被删除(即,替换为 nothing)。如果您只输入""(后跟),您会收到相同的消息。你能举一个例子,bash 说类似 <empty string>而不是只写一个空字符串吗? …(续) -
(续)... 你能找出
if "" ; then …和if "nonexistent" ; then …之间的任何实际区别吗? -
@KeithThompson:我同意这是一个有趣的问题。鉴于此页面上提供的所有具有启发性的示例,我很惊讶没有人提供与
if "" ; then …相同的if "$(true)" ; then …和command='' ; if "$command" ; then …(带引号)。