()中的错误的含义
我找不到任何一个简单直接的资源来说明下面这个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;
这样我解决了我的问题。 希望对你也有帮助。