[:太多的争论]的含义;来自if[](方括号)的错误

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

错误:

-bash: [: too many arguments

Google-friendly版本: bash open square bracket colon too many arguments

背景:一个if条件,用一个简单的比较操作符,如=,大于etc,例如:

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

如果你的$VARIABLE是一个包含空格或其他特殊字符的字符串,并且使用单个方括号(这是test命令的快捷方式),那么该字符串可能被分成多个单词。每一个都被当作一个单独的参数。

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

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


if [ $VARIABLE == 0 ]; then
# fails as if you wrote:
# if [ hello world == 0 ]
fi

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


很容易解决

将变量输出用双引号括起来,强制它保持为一个字符串(因此是一个参数)。例如,

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

就这么简单。但是如果你也不能保证你的变量不是一个空字符串,或者一个除了空格什么都不包含的字符串,那么跳到下面的“Also caution…”。


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

然而,这只存在于bash(显然还有korn和zsh)中,因此可能与/bin/sh等调用的默认shell不兼容。

这意味着在某些系统中,它可能在控制台工作,但在其他地方调用时就不行了,比如从cron调用取决于所有内容的配置方式。

它看起来是这样的:

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

如果你的命令包含像这样的双方括号,你在日志中得到错误,但它在控制台工作,尝试将[[替换为这里建议的替代方法,或者,确保运行你的脚本的任何程序都使用支持[[new test的shell。


还要注意[: unary operator expected错误

如果您看到“too many arguments”错误,则很可能是从具有不可预知输出的函数获得的字符串。如果也有可能得到一个空字符串(或所有空白字符串),即使使用上述“快速修复”,这也将被视为零参数,并且使用[: unary operator expected将失败

如果你习惯了其他语言,这是同样的“陷阱”——你不会期望变量的内容在它被求值之前像这样有效地打印到代码中。

下面是一个防止[: too many arguments[: unary operator expected错误的示例:如果输出为空,则将输出替换为默认值(在本例中为0),并将整个输出使用双引号括起来:

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

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


最后注意:由于[test的快捷方式,因此上述所有内容对于错误test: too many arguments(以及test: unary operator expected)也是成立的。

刚刚碰到这篇文章,通过得到相同的错误,试图测试两个变量这两个是否为空(或非空)。结果是复合比较- 7.3。其他比较操作符-高级bash脚本指南;我想我应该注意以下几点:

  • 我使用-e,认为它一开始意味着“空”;但这意味着“文件存在”-使用-z测试空变量(字符串)
  • 字符串变量需要加引号
  • 对于复合逻辑与比较:
    • 使用两个__abc0和&&它们:[ ... ] && [ ... ]
    • 或在单个test: [ ... -a ... ]中使用-a操作符
    • 李< / ul > < / >

    下面是一个工作命令(搜索目录中的所有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(单个方括号[)检查字符串是否相等时,你必须在“is equal”操作符之间有一个空格,在这种情况下是一个“equals”=符号(尽管两个等号==似乎也可以接受为相等操作符)。因此,这将失败(无声地):

    $ 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;

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

有时候如果你不小心触碰了键盘,移开了一个空格。

if [ "$myvar" = "something"]; then
do something
fi

将触发此错误消息。注意']'前面的空格是必须的。

你可以得到[: too many arguments[: a: binary operator expected错误的另一种情况是,如果你试图测试所有参数"$@"

if [ -z "$@" ]
then
echo "Argument required."
fi

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

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

我也面临着同样的问题。@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

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

export "Name"="John"
export "age"="31"
export "birthyear"="1990"
export "gender"="M"

下面的语法,我得到预期的输出。 正确的语法:< / p >

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

有几点我们必须牢记在心

  1. 使用“;”而不是“
  2. 用-a代替&&
  3. 在操作符[a=b]前后加空格,不要在if条件中使用[a=b]

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