为什么我得到“一元运算符预期”错误?

时间:2013-10-30 18:32:24

标签: bash shell

我正在编写一个shell脚本来简化我的开发工作流程。

我需要参考哪个主题文件夹,并在该目录上启动grunt watch

如果我在没有必要参数的情况下调用脚本,我当前正在打印警告,需要将主题指定为命令行参数。

我想打印一份可用选项列表,例如主题目录

这就是我到目前为止......

THEME=$1

if [ $THEME == '' ]
then
    echo 'Need to specify theme'
else
    cd 'workspace/aws/ghost/'$THEME'/'
    grunt watch
fi

理想情况下,我会将echo行的输出替换为主目录父目录的ls,如此

THEME=$1

if [ $THEME == '' ]
then
    echo 'Need to specify theme from the following'
    ls workspace/aws/ghost
else
    cd 'workspace/aws/ghost/'$THEME'/'
    grunt watch
fi

然而,这给了我以下错误

./ghost_dev.sh: line 3: [: ==: unary operator expected

3 个答案:

答案 0 :(得分:43)

您需要$THEME周围的引号:

if [ $THEME == '' ]

否则,当您未指定主题时,$THEME会扩展为空,并且shell会看到此语法错误:

if [ == '' ]

添加引号,如下:

if [ "$THEME" == '' ]

$THEME的扩展会产生这种有效的比较:

if [ "" == '' ]

运行时语法错误的容量对于那些背景在更传统的编程语言中的人来说可能是令人惊讶的,但是命令shell(至少是Bourne传统中的那些)解析代码的方式有些不同。在许多情况下,shell参数的行为更像宏而不是变量;这种行为提供了灵活性,但也为不谨慎的人创造了陷阱。

由于您标记了此问题 bash ,因此值得注意的是,bash(和ksh / zsh)中可用的“新”测试语法中的参数扩展结果没有进行任何分词处理,即[[ ...... ]]。所以你也可以这样做:

if [[ $THEME == '' ]]

{@ 3}}列出了您可以不带引号的地方。但是总是引用参数扩展是一个很好的习惯,除非你明确要求分词(即便如此,看看数组是否会解决你的问题)。

使用-z测试运算符而不是与空字符串相等会更加惯用:

if [ -z "$THEME" ]

在这种简单的情况下,您在技术上不需要引号; [ -z ]评估为真。但是如果你有一个更复杂的表达式,解析器会变得混乱,所以最好总是使用引号。当然,[[ ... ]]也不需要引号:

if [[ -z $THEME ]]

但是[[ ... ]]不是POSIX标准的一部分;就此而言,==也不是。因此,如果您关心与其他POSIX shell的严格兼容性,请坚持使用引用解决方案并使用-z或单=

答案 1 :(得分:4)

如果[ "$THEME" ]未定义或为空字符串,

$THEME将评估为false,否则为true。见http://www.gnu.org/software/bash/manual/html_node/Bash-Conditional-Expressions.html#Bash-Conditional-Expressions。您可以重新排列if语句以利用此行为并使条件更简单:

if [ "$THEME" ]; then
    cd 'workspace/aws/ghost/'$THEME'/'
    grunt watch
else
    echo 'Need to specify theme from the following'
    ls workspace/aws/ghost
fi

"$THEME"需要使用双引号,以防其值包含空格。

答案 2 :(得分:-1)

请使用双引号更正语法。

 if [ "$THEME" == "" ]; then
     echo 'Need to specify theme from the following'
     ls workspace/aws/ghost
 fi
相关问题