Значение ошибки" [: слишком много аргументов " из if [] (квадратные скобки)

Я не мог найти ни одного простого простого ресурса, разъясняющего значение и исправляющего следующую ошибку оболочки BASH, поэтому я публикую то, что нашел после исследования.

ошибки:

-bash: [: too many arguments

Google-дружественные версии: bash open square bracket colon too many arguments.

контекст: условие if в квадратных скобках с простым оператором сравнения, таким как equals, больше, чем etc, например:

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

4 ответов


если $VARIABLE - это строка, содержащая пробелы или другие специальные символы и используются квадратные скобки (что является ярлыком для test command), то строка может быть разделена на несколько слов. Каждый из них рассматривается как отдельный аргумент.

, так что одна переменная разбивается на множество аргументов:

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 command).

это существует только в bash (и, по-видимому, korn и zsh), однако, и поэтому может быть несовместимо с оболочками по умолчанию, вызываемыми /bin/sh etc. Это означает, что в некоторых системах, например, он может работать с консоли, но не с cron в зависимости от того, как все настроено.

это будет выглядеть так:

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

также остерегайтесь [: unary operator expected ошибка

если вы видите ошибку "слишком много аргументов", скорее всего, вы получаете строку из функции с непредсказуемым выходом. Если также можно получить пустую строку (или вся строка пробелов), это будет рассматриваться как нулевые аргументы даже с вышеупомянутым "быстрым исправлением" и завершится неудачей с [: unary operator expected

это то же самое "gotcha", если вы привыкли к другим языкам - вы не ожидаете, что содержимое переменной будет эффективно напечатано в такой код перед его выполнением.

вот пример, который предотвращает оба [: too many arguments и [: unary operator expected ошибки: замена вывода значением по умолчанию, если он пуст (в этом примере 0), с двойными кавычками, обернутыми вокруг всего этого:

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

(здесь действие произойдет, если переменная $равна 0 или пуста. Естественно, вы должны изменить 0 (значение по умолчанию), значение по умолчанию, если другое поведение разыскивается)


Конечная нота: С [ ярлык для test, все вышесказанное также верно для ошибки test: too many arguments (а также test: unary operator expected)


просто наткнулся на этот пост, получив ту же ошибку, пытаясь проверить, являются ли две переменные и пустые (или не пустые). Это оказывается соединение сравнения - 7.3. Другие Операторы Сравнения-Advanced Bash-Руководство По Скриптам; и я подумал, что должен отметить следующее:

  • я -e сначала это означает "пустой"; но это означает, что "файл существует" - используйте -z для тестирования пустые переменная (строка)
  • строковые переменные должны быть указаны
  • для составного логического и сравнения, либо:
    • использовать два tests и && них: [ ... ] && [ ... ]
    • или использовать -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

edit 12 aug 2013: связанная проблема Примечание:

обратите внимание, что при проверке равенства строк с классическим 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

У меня была такая же проблема с моими скриптами. Но когда я сделал некоторые изменения, это сработало для меня. Мне это понравилось: -

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

вызвать это сообщение об ошибке. Не требуется пространство перед"]".