Присвоение переменной вне оператора case

8

Во многих языках можно присваивать результат оператора case / switch переменной, а не повторять присвоение переменной много раз внутри оператора case. Можно ли сделать что-то подобное в оболочке Bash?

color_code=$(case "$COLOR" in
  (red)    1;;
  (yellow) 2;;
  (green)  3;;
  (blue)   4;;
esac)

(Или, как в стороне, в любых других оболочках?)

иконоборец
источник
У вас есть дополнительные (с. В противном случае это нормально.
HalosGhost

Ответы:

6

variable=$(...)Конструкция будет принимать стандартный вывод любой команды в $(...)и назначить его variable. Таким образом, чтобы получить variableприсвоенный вам путь, значения должны быть отправлены на стандартный вывод. Это легко сделать с помощью echoкоманды:

color_code=$(case "$COLOR" in
  red)    echo 1;;
  yellow) echo 2;;
  green)  echo 3;;
  blue)   echo 4;;
esac)

Это будет работать bashкак и все другие оболочки POSIX.

Необязательные левые парены

В соответствии со стандартом POSIX левые символы в caseвыражении являются необязательными, а также работает следующее:

color_code=$(case "$COLOR" in
  (red)    echo 1;;
  (yellow) echo 2;;
  (green)  echo 3;;
  (blue)   echo 4;;
esac)

Как отмечает Жиль в комментариях, не все оболочки принимают обе формы в сочетании с $(...): для внушительно подробной таблицы совместимости см. «$ ()» Подстановка команд вместо встроенной «)» .

John1024
источник
На одной странице, которую я проверил (я не помню, где она была), было указано, что открытие (является необязательным. Я думал , что это могло бы помочь избежать позволить )быть неверно истолкована как закрытие )для $(...)выражения.
иконоборчество
@iconoclast Да. Открытие не (является обязательным: код работает так же, без или без них. Я оставил их только потому, что, к лучшему или к худшему, это традиция. Ключевой частью предлагаемого решения является использование echo.
John1024
1
@iconoclast Старые (предварительно POSIX) оболочки не позволяют отверстие (для caseмоделей, но некоторые снаряды делали и требовали открытия , (когда caseиспользуются в подстановке команд. Современные оболочки хороши в любом случае. См. In-ulm.de/~mascheck/various/cmd-subst
Жиль "
1
@ Жиль Спасибо за эту информацию. Глубина ваших знаний, как всегда, впечатляет.
John1024
2

color_code=$(…)присваивает выходные данные команды переменной color_code, с окончательными символами новой строки. Так что вам нужно произвести какой-то вывод. Код, который вы написали, пытается выполнить 1как команду.

Вы можете использовать эту идиому. Обратите внимание, что color_codeбудет пустым, если $COLORне поддерживается ни одно из поддерживаемых значений.

color_code=$(case "$COLOR" in
  (red)    echo 1;;
  (yellow) echo 2;;
  (green)  echo 3;;
  (blue)   echo 4;;
esac)

Но это не очень идиоматично. Язык оболочки ориентирован на простые комбинации простых команд. Эта большая командная замена неудобна. Подстановка команд создает подоболочку, которая медленнее, чем простой метод:

case "$COLOR" in
  red)    color_code=1;;
  yellow) color_code=2;;
  green)  color_code=3;;
  blue)   color_code=4;;
esac

Основное семантическое различие между этими двумя подходами заключается в том, что $(…)создается подоболочка, так что любое присвоение, выход, перенаправление и т. Д., Которые выполняются внутри, не оказывают влияния снаружи.

Жиль "ТАК - перестань быть злым"
источник