if [](方括号)中“[: too many arguments”错误的含义

Posted

技术标签:

【中文标题】if [](方括号)中“[: too many arguments”错误的含义【英文标题】:Meaning of "[: too many arguments" error from if [] (square brackets) 【发布时间】:2012-11-26 16:50:09 【问题描述】:

我找不到任何一个简单直接的资源来说明以下 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 

【问题讨论】:

产生这个特定错误的代码在哪里? 另见When to wrap quotes around a shell variable? 【参考方案1】:

我也遇到了同样的问题。 @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"

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

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

有几点我们需要牢记

    用“”代替“” 使用 -a 代替 && 在运算符号前后加空格,如 [a = b],不要在 if 条件中用作 [a=b]

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

【讨论】:

【参考方案2】:

刚刚碰到这篇文章,遇到同样的错误,试图测试两个变量是否为空(或非空)。原来是compound comparison - 7.3. Other Comparison Operators - Advanced Bash-Scripting Guide;我想我应该注意以下几点:

我用-e一开始以为它的意思是“空的”;但这意味着“文件存在” - 使用-z 测试空的变量(字符串) 字符串变量需要加引号 对于复合逻辑 AND 比较,可以: 使用两个tests 和&& 他们:[ ... ] && [ ... ] 或在单个test 中使用-a 运算符:[ ... -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

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

...但是添加空格 - 一切看起来都不错:

$ 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

【讨论】:

您能提供一个((A || B) && C) 的bash shell 示例吗? 请看问题382642514964805 这真的不是一个有用的答案,因为它没有向您展示如何将命令完全包含在方括号内,例如,如果存在循环,则需要这样做。跨度> 【参考方案3】:

如果您的$VARIABLE 是包含空格或其他特殊字符的字符串and single square brackets are used(这是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 

就这么简单。但是如果您也不能保证您的变量不是空字符串或只包含空格的字符串,请跳到下面的“还要注意...” .


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

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

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

看起来像这样:

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

如果您的命令包含这样的双方括号,并且您在日志中遇到错误,但它可以从控制台运行,请尝试将 [[ 替换为此处建议的替代方法,或者确保运行您的脚本的任何内容都使用支持[[又名new test


还要注意[: unary operator expected 错误

如果您看到“参数过多”错误,则很可能您从函数中获取了一个输出不可预测的字符串。 如果还可以获得空字符串(或所有空白字符串),即使使用上述“快速修复”,这也将被视为零参数,并且会因[: 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

【讨论】:

更好的方法是i=$(some_command); i=$((i)); if [ "$i" == 0 ] ... 我遇到了一个问题,即使用 BASH 作为解释器的 Shellscript 在通过终端执行时运行正常,但在通过 Crontab 执行时出现此类故障并通过 Postfix 发送本地电子邮件,通知此错误我发现,有一个 IF 用于具有特殊字符的变量。双引号救了我的命。谢谢你:)!【参考方案4】:

您可能会收到 [: 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 ]。 ($# 是参数的数量)。

【讨论】:

【参考方案5】:

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

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

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

【讨论】:

我认为这会导致不同的语法错误,例如:line 21: [: missing `]'【参考方案6】:

我的脚本也有同样的问题。但是当我做了一些修改时,它对我有用。我确实喜欢这样:-

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

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

【讨论】:

不需要export子进程不使用的变量。

以上是关于if [](方括号)中“[: too many arguments”错误的含义的主要内容,如果未能解决你的问题,请参考以下文章

if [](方括号)中“[: too many arguments”错误的含义

if 括号 if(...) 中语句的求值顺序是啥? [复制]

使用 if 时缺少右括号

在C语言中,if和else if是否在不加花括号的情况下也是一个复合语句

if括号中的潜规则

C语言这三个if括号里是啥意思