ChatGPT解决这个技术问题 Extra ChatGPT

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

我找不到任何一个简单直接的资源来说明以下 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 
产生此特定错误的代码在哪里?

u
user56reinstatemonica8

如果您的 $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 

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

还要注意 [: 一元运算符预期的错误

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

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

我最初使用 -e 认为它的意思是“空的”;但这意味着“文件存在” - 使用 -z 测试空变量(字符串)

字符串变量需要加引号

对于复合逻辑 AND 比较,可以:使用两个测试并 && 它们:[ ... ] && [ ... ] 或在单个测试中使用 -a 运算符: [ ... -a ... ]

使用两个测试和 && 他们: [ ... ] && [ ... ]

或在单个测试中使用 -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(单个方括号 [)检查字符串相等时,您必须在“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

您能否提供一个 ((A || B) && C) 的 bash shell 示例?
请参阅问题 382642514964805
这实际上对答案没有那么有用,因为它没有向您展示如何将命令完全包含在方括号内,例如,如果存在循环,则需要这样做。
w
wisbucky

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


H
Harsh Wardhan Gupta

我也面临同样的问题。 @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 条件中使用 as [ a=b ]

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


K
Kemin Zhou

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

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

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


我认为这会导致不同的语法错误,例如: line 21: [: missing `]'
K
Ken Y-N

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

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

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


无需export 子流程未使用的变量。