Значение ошибки" [: слишком много аргументов " из 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 ответа:
если
$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;
таким образом, я решил свою проблему. Надеюсь, что это поможет и вам тоже.