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


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

ошибки:

-bash: [: too many arguments

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

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

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

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 

вот так просто. но перейти к "также остерегайтесь..."ниже, если вы также не можете гарантировать, что ваша переменная не будет пустой строкой или строкой, которая не содержит ничего, кроме пробелов.


или альтернативный исправление это используйте двойные квадратные скобки (что является ярлыком для ).

это существует только в 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-Scripting Guide; и я подумал, что должен отметить следующее:

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

редактировать 12 августа 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

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