if [](方括号)中"[:太多参数"错误的含义

use*_*ca8 185 bash arguments if-statement

我找不到任何一个简单直接的资源,用于解释以下BASH shell错误的含义和修复,所以我发布了我在研究之后发现的内容.

错误:

-bash: [: too many arguments
Run Code Online (Sandbox Code Playgroud)

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

上下文:单个方括号中的if条件,带有一个简单的比较运算符,如equals,大于等,例如:

VARIABLE=$(/some/command);
if [ $VARIABLE == 0 ]; then
  # some action
fi 
Run Code Online (Sandbox Code Playgroud)

use*_*ca8 326

如果您$VARIABLE的字符串包含空格或其他特殊字符,并且使用单个方括号(这是test命令的快捷方式),则字符串可能会拆分为多个单词.其中每一个都被视为一个单独的参数.

因此,一个变量被分成许多参数:

VARIABLE=$(/some/command);  
# returns "hello world"

if [ $VARIABLE == 0 ]; then
  # fails as if you wrote:
  # if [ hello world == 0 ]
fi 
Run Code Online (Sandbox Code Playgroud)

对于放下包含空格或其他特殊字符的字符串的任何函数调用都是如此.


轻松修复

用双引号包装变量输出,强制它保持为一个字符串(因此一个参数).例如,

VARIABLE=$(/some/command);
if [ "$VARIABLE" == 0 ]; then
  # some action
fi 
Run Code Online (Sandbox Code Playgroud)

就那么简单.但是如果你也不能保证你的变量不是空字符串,或者只包含空格的字符串,请跳到下面的"注意......".


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

这仅存在于bash中(显然是korn和zsh),因此可能与由/bin/sh等调用的默认shell不兼容.这意味着在某些系统上,例如,它可能来自控制台而不是来自cron,取决于一切如何已配置.

它看起来像这样:

VARIABLE=$(/some/command);
if [[ $VARIABLE == 0 ]]; then
  # some action
fi 
Run Code Online (Sandbox Code Playgroud)

还要注意[[错误

如果您看到"参数太多"错误,则可能是从具有不可预测输出的函数中获取字符串.如果它也可以获得一个空字符串(或所有空白字符串),即使使用上面的"快速修复",这也将被视为零参数,并且会失败[[

如果你习惯了其他语言,那就是'gotcha' - 你不希望变量的内容在评估之前有效地打印到代码中.

这是一个阻止new test[: unary operator expected错误的例子:如果输出为空(在本例中为[: unary operator expected),则用默认值替换输出,并用双引号括起整个事物:

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

(这里,如果$ VARIABLE为0,则会发生操作,或者为空.当然,如果需要不同的行为,您应该将0(默认值)更改为其他默认值)


最后的注意事项:既然[: too many arguments是一个快捷方式[: unary operator expected,以上所有内容对于错误也是如此0(也是[)


sda*_*aau 10

只是碰到这篇文章,通过获得相同的错误,试图测试两个变量是否空(或非空).结果证明这是一个复合比较 - 7.3.其他比较运算符 - 高级Bash-Scripting指南 ; 我想我应该注意以下几点:

  • -e以为它起初意味着"空"; 但这意味着"文件存在" - -z用于测试空变量(字符串)
  • 需要引用字符串变量
  • 对于复合逻辑AND比较,要么:
    • 使用两个test&&他们:[ ... ] && [ ... ]
    • -a单独使用运算符test:[ ... -a ... ]

这是一个工作命令(搜索目录中的所有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
Run Code Online (Sandbox Code Playgroud)

编辑2013年8月12日:相关问题说明:

请注意,在使用经典test(单方括号[)检查字符串相等性时,必须在"等于"运算符之间有一个空格,在这种情况下是一个单"等于" =符号(尽管两个等于'符号==似乎被接受为相等运营商也是).因此,这失败了(默默地):

$ 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
Run Code Online (Sandbox Code Playgroud)

...但是添加空间 - 一切看起来都很好:

$ 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
Run Code Online (Sandbox Code Playgroud)


Kem*_*hou 5

有时如果您不小心触碰键盘并删除了一个空格。

if [ "$myvar" = "something"]; then
    do something
fi
Run Code Online (Sandbox Code Playgroud)

会触发这个错误信息。请注意“]”之前的空格是必需的。

  • 我认为这会导致不同的语法错误,例如:第 21 行:[:缺少`]' (3认同)

wis*_*cky 5

另一个可能会出现[: too many arguments[: a: binary operator expected错误的情况是,如果您尝试测试所有参数"$@"

if [ -z "$@" ]
then
    echo "Argument required."
fi
Run Code Online (Sandbox Code Playgroud)

如果您调用foo.sh或 ,它可以正常工作foo.sh arg1。但是如果你传递多个参数,比如foo.sh arg1 arg2,你会得到错误。这是因为它被扩展为[ -z arg1 arg2 ],这不是有效的语法。

检查参数是否存在的正确方法是[ "$#" -eq 0 ]. ($#是参数的数量)。


小智 5

我也面临同样的问题。@sdaau 的回答以合乎逻辑的方式帮助了我。我正在做的事情对我来说似乎在语法上是正确的,但出现了太多参数错误。

错误的语法:

if [ $Name != '' ] && [ $age != '' ] && [ $sex != '' ] && [ $birthyear != '' ]  && [ $gender != '' ] 
then
    echo "$Name"
    echo "$age"
    echo "$sex"
    echo "$birthyear"
    echo "$gender"
else
    echo "Enter all the values"
fi
Run Code Online (Sandbox Code Playgroud)

在上面的 if 语句中,如果我传递如下所述的变量值,那么我也会收到语法错误

export "Name"="John"
export "age"="31"
export "birthyear"="1990"
export "gender"="M"
Run Code Online (Sandbox Code Playgroud)

使用下面的语法我得到了预期的输出。正确的语法:

if [ "$Name" != ""  -a  "$age" != ""  -a  "$sex" != ""  -a  "$birthyear" != ""   -a  "$gender" != "" ] 
then
    echo "$Name"
    echo "$age"
    echo "$sex"
    echo "$birthyear"
    echo "$gender"
else
    echo "it failed"
fi
Run Code Online (Sandbox Code Playgroud)

有几点我们需要牢记

  1. 使用“”代替“”
  2. 使用 -a 代替 &&
  3. 在运算符号之前和之后放置空格,如 [ a = b],不要在 if 条件中使用 as [ a=b ]

因此上述解决方案对我有用!