()中的错误的含义

我找不到任何一个简单直接的资源来说明下面这个BASH shell错误的含义和修复方法,所以我把它发现后发现了。

错误:

-bash: [: too many arguments 

Google友好的版本: bash open square bracket colon too many arguments

上下文:在单个方括号中使用简单的比较运算符(如等于,大于等)的if条件,例如:

 VARIABLE=$(/some/command); if [ $VARIABLE == 0 ]; then # some action fi 

如果$VARIABLE是一个包含空格或其他特殊字符的string, 并且使用了单个方括号 (这是test命令的快捷方式),那么该string可能会被分成多个单词。 这些被视为一个单独的论点。

所以一个variables被分解成许多参数

 VARIABLE=$(/some/command); # returns "hello world" if [ $VARIABLE == 0 ]; then # fails as if you wrote: # if [ hello world == 0 ] fi 

任何函数调用都会放下包含空格或其他特殊字符的string。


易于修复

将variables输出用双引号括起来,迫使它保持为一个string(因此是一个参数)。 例如,

 VARIABLE=$(/some/command); if [ "$VARIABLE" == 0 ]; then # some action fi 

就那么简单。 但是如果你不能保证你的variables不是一个空string,或者一个只包含空格的string,那么跳到下面的“也要当心…”。


或者, 另一种修复方法是使用双方括号(这是new test命令的快捷方式)。

这只存在于bash中(而且显然是korn和zsh),所以可能不兼容默认的由/bin/sh调用的shell等。这意味着在某些系统上,例如,它可能在控制台上工作,但不能在cron ,这取决于如何configuration一切。

它看起来像这样:

 VARIABLE=$(/some/command); if [[ $VARIABLE == 0 ]]; then # some action fi 

还要小心[: unary operator expected错误

如果你看到“参数太多”的错误,你可能会得到一个函数的string,输出不可预知。 如果也可以得到一个空string (或者所有的空白string),即使有上面​​的“快速修复”,也可以将其视为零参数,并且会失败,因为[: unary operator expected会使用[: unary operator expected

如果你习惯于其他语言,那么它就是一个“疑难杂症” – 在评估之前,你不希望将variables的内容有效地打印到代码中。

下面是一个例子,它可以防止[: too many arguments[: unary operator expected errors:如果输出为空(如本例中为0 ),用双引号将输出replace为默认值:

 VARIABLE=$(/some/command); if [ "${VARIABLE:-0}" == 0 ]; then # some action fi 

(在这里,如果$ VARIABLE是0或者是空的,动作会发生,当然,如果需要不同的行为,你应该把0(默认值)改为一个不同的默认值)


最后一点:因为[test的捷径,所以上面的错误test: too many arguments也是如此test: too many arguments (也是test: unary operator expected

刚碰到这个post,通过得到相同的错误,试图testing如果两个variables都是空的(或非空)。 这原来是一个复合比较 – 7.3。 其他比较运算符 – 高级Bash脚本指南 ; 我想我应该注意以下几点:

  • 我曾经以为 – 一开始就以为它是空的 但这意味着“文件存在” – 使用-z来testing空variables (string)
  • stringvariables需要引用
  • 对于复合逻辑与比较,可以是:
    • 使用两个test&&他们: [ ... ] && [ ... ]
    • 或在单个test使用-a运算符: [ ... -a ... ]

这是一个工作命令(search目录中的所有txt文件,并且倾倒那些grep发现包含两个单词的文件):

 find /usr/share/doc -name '*.txt' | while read file; do \ a1=$(grep -H "description" $file); \ a2=$(grep -H "changes" $file); \ [ ! -z "$a1" -a ! -z "$a2" ] && echo -e "$a1 \n $a2" ; \ done 

编辑2013年8月12日:相关的问题注意:

请注意,当使用经典test (单方括号[ )检查string相等性时, 必须在“is equal”运算符之间有一个空格,在这种情况下它是单字“equals” =符号(尽pipe两个等于“也被平等接受者接受)。 因此,这失败(默默):

 $ if [ "1"=="" ] ; then echo A; else echo B; fi A $ if [ "1"="" ] ; then echo A; else echo B; fi A $ if [ "1"="" ] && [ "1"="1" ] ; then echo A; else echo B; fi A $ if [ "1"=="" ] && [ "1"=="1" ] ; then echo A; else echo B; fi A 

…但增加空间 – 一切看起来不错:

 $ if [ "1" = "" ] ; then echo A; else echo B; fi B $ if [ "1" == "" ] ; then echo A; else echo B; fi B $ if [ "1" = "" -a "1" = "1" ] ; then echo A; else echo B; fi B $ if [ "1" == "" -a "1" == "1" ] ; then echo A; else echo B; fi B 

我的脚本也有同样的问题。 但是,当我做了一些修改它为我工作。 我是这样做的: –

 export k=$(date "+%k"); if [ $k -ge 16 ] then exit 0; else echo "good job for nothing"; fi; 

这样我解决了我的问题。 希望对你也有帮助。