Что означает «тест $ 2 &&» в этом сценарии bash?

Я смотрю скрипт bash со следующим кодом:

#!/bin/sh set -e # Exit if any command fails # If multiple args given run this script once for each arg test $2 && { for arg in $@ do $0 $arg done exit } . . . 

Как упоминалось в комментарии, цель состоит в том, чтобы «запустить скрипт для каждого аргумента, если его несколько» У меня есть код для запуска, чтобы проверить это:

 # install-unit # If multiple args given run this script once for each arg test $2 && { echo "\$0: $0" echo "\$1: $1" echo "\$2: $2" echo "test \$2 && is true" } test $2 && { # note this is just a regular bash for loop # http://goo.gl/ZHpBvT for arg in $@ do $0 $arg done exit } echo "running: $1" 

который дает следующее:

 sh ❯ ./multiple-run.sh cats and dogs and stuff $0: ./multiple-run.sh $1: cats $2: and test $2 && is true running: cats running: and running: dogs running: and running: stuff sh ❯ ./multiple-run.sh cats running: cats 

Я бы хотел, чтобы кто-то распаковал test $2 && {} и встроенную оболочку exit . Сначала я думал, что test $2 проверяет, есть ли больше аргументов, и, возможно, это так, но выглядит странно, потому что кажется, что есть два выражения, разделенные символом «и» && , и я также просто смущен тем, что делает этот вывод.

Простые английские объяснения с примерами и ссылками на документацию оценены 🙂

Благодаря!

Редактировать: Спасибо Stéphane Chazelas за это. Для тех, кто запутался в синтаксисе for for loop, проверьте номер 3 в этой статье geekstuff . Обобщить:

 echo "positional parameters" for arg do echo "$arg" done echo "\nin keyword" for arg in "$@" do echo "$arg" done 

дает нам:

 ❯ ./for-loop-positional.sh cats and dogs positional parameters cats and dogs in keyword cats and dogs 

2 Solutions collect form web for “Что означает «тест $ 2 &&» в этом сценарии bash?”

Это неправильный способ написать:

 #!/bin/sh - set -e # Exit if any command fails # If multiple args given run this script once for each arg if [ "$#" -gt 1 ]; then for arg do "$0" "$arg" done exit fi 

Я думаю, что автор хотел сделать, это проверить, является ли второй аргумент непустой строкой (это не то же самое, что проверка того, есть ли более одного аргумента, поскольку второй аргумент может быть передан, но будет пустой строкой) ,

 test somestring 

Краткая форма

 test -n somestring 

Возвращает true, если somestring не является пустой строкой. ( test '' возвращает false, test anythingelse возвращает true (но остерегайтесь test -t в некоторых оболочках, которые проверяют, является ли stdout вместо терминала)).

Однако автор забыл кавычки вокруг переменной (по всем переменным на самом деле). Это означает, что содержание в $2 зависит от оператора split + glob. Так что если $2 содержит символы $IFS (пробел, табуляция и новая строка по умолчанию) или символы glob ( * , ? , [...] ), это не будет работать должным образом.

И если $2 пуст (например, когда передано менее 2 аргументов или второй аргумент пуст), test $2 становится test , а не test '' . test не получает никакого аргумента вообще (пустым или иным).

К счастью, в этом случае test без аргументов возвращает false. Это немного лучше, чем test -n $2 который вместо этого вернул бы true (так как это станет test -n , так же, как test -n -n ), поэтому в некоторых случаях код будет работать.

Подводить итоги:

  • для проверки наличия двух или более аргументов:

     [ "$#" -gt 1 ] 

    или

     [ "$#" -ge 2 ] 
  • проверить, является ли переменная непустой:

     [ -n "$var" ] [ "$var" != '' ] [ "$var" ] 

    все из которых надежны в реализациях POSIX [ , но если вам приходится иметь дело с очень старыми системами, возможно, вам придется использовать

     [ '' != "$var" ] 

    вместо этого для реализаций [ которые задувают значения $var like = , -t , (

  • чтобы проверить, определена ли переменная (которая может быть использована для проверки того, передан ли сценарий второй аргумент, но использование $# намного проще для чтения и более идиоматическое):

     [ "${var+defined}" = defined ] 

(или эквивалент с test формой. Использование [ alias для test команды более распространено).


Теперь о разнице между cmd1 && cmd2 и if cmd1; then cmd2; fi if cmd1; then cmd2; fi if cmd1; then cmd2; fi .

Оба запускают cmd2 только в том случае, если cmd1 успешно. Разница в этом случае заключается в том, что статус выхода из общего списка команд будет таким же, как и в последней команде, которая запускается в && case (так что код отказа, если cmd1 не возвращает true (хотя это не cmd1 set -e здесь)), тогда как в случае if это будет то, что cmd2 или 0 (успех), если cmd2 не запущен.

Поэтому в случаях, когда cmd1 должен использоваться как условие (когда его отказ не рассматривается как проблема ), его обычно лучше использовать if особенно если это последнее, что вы делаете в скрипте, поскольку это определит выход вашего сценария положение дел. Он также обеспечивает более четкий код.

Форма cmd1 && cmd2 чаще используется в качестве условий, таких как:

 if cmd1 && cmd2; then... while cmd1 && cmd2; do... 

То есть в контексте, где мы заботимся о статусе выхода обеих этих команд.

test $2 && some_command состоит из двух команд:

  • test $2 проверяет, имеет ли строка после разложения второго аргумента ( $2 ) ненулевую длину, т. е. обязательно проверяет test -n $2 ( [ -n $2 ] ). Обратите внимание, что, поскольку вы не использовали котировки около $2 , test захлестнет значениями с пробелами. Здесь вы должны использовать test "$2" .

  • && является оператором оценки короткого замыкания, который указывает, что команда после && будет запускаться только в том случае, если команда перед ее успешным запуском, т.е. имеет код выхода 0. Таким образом, в приведенном выше примере some_command будет выполняться только в том случае, если test $2 успешным, т.е. если строка имеет ненулевую длину, тогда будет выполняться some_command .

  • Нужна помощь с сценарием командной строки сетевого администратора
  • Сценарии конфигурации VMware: могу ли я использовать PowerCLI?
  • Сохранять форматирование, когда командный вывод отправляется в переменную?
  • Использование sed для замены строки со многими специальными символами?
  • Почему моя петля не продолжается должным образом в моей игре с ножницами из каменной бумаги?
  • Скрипт, который выводит общее количество строк во всех текстовых файлах, передаваемых в качестве аргументов
  • Правильно использовать бит setuid
  • Имитация нажатия клавиши PrintScreen
  • Использовать xvfb для автоматизации программы X
  • Почему сочетание «меньше» и «скрипт» прерывает окончания строк?
  • Сравните два файла и распечатать совпадения
  • Linux и Unix - лучшая ОС в мире.