25

我正在编写一个 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
4

3 回答 3

57

你需要这里的报价$THEME

if [ $THEME == '' ]

否则,当您不指定主题时,$THEME将展开为空,并且 shell 会看到以下语法错误:

if [ == '' ]

添加引号后,如下所示:

if [ "$THEME" == '' ]

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

if [ "" == '' ]

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

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

if [[ $THEME == '' ]]

此处列出了无需引号即可逃脱的地方。但是总是引用参数扩展是一个好习惯,除非你明确想要分词(即使那样,看看数组是否能解决你的问题)。

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

if [ -z "$THEME" ]

在这种简单的情况下,从技术上讲,您不需要引号;[ -z ]评估为真。但是如果你有一个更复杂的表达式,解析器会感到困惑,所以最好总是使用引号。当然,[[......]]这里也不需要任何东西:

if [[ -z $THEME ]]

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

于 2013-10-30T18:33:59.730 回答
4

[ "$THEME" ]$THEME如果未定义或为空字符串,将评估为假,否则为真。请参阅http://www.gnu.org/software/bash/manual/html_node/Bash-Conditional-Expressions.html#Bash-Conditional-Expressions。你可以重新排列你的 if 语句来利用这种行为,并有一个更简单的条件:

如果 [ "$主题" ]; 然后
    cd '工作区/aws/ghost/'$THEME'/'
    咕哝手表
别的
    echo '需要从以下指定主题'
    ls 工作区/aws/ghost
菲

"$THEME"需要用双引号括起来,以防它的值包含空格。

于 2013-10-30T20:04:24.783 回答
-1

请用双引号更正语法。

 if [ "$THEME" == "" ]; then
     echo 'Need to specify theme from the following'
     ls workspace/aws/ghost
 fi
于 2013-10-30T18:41:10.393 回答