Операторы case оцениваются как строки

Я поймал ошибку функционального программирования, поэтому, естественно, для меня ничего хорошего не достаточно.;)

Итак, в bash можно написать:

case $status in
  "foo") status="bar" ;;
  "baz") status="buh" ;;
   *) status=$status ;;
esac

но я боюсь опечаток, поэтому предпочитаю писать:

status=case $status in
  "foo") "bar" ;;
  "baz") "buh" ;;
  *) $status ;;
esac

Вторая форма недействительна, так как случай оценивает код выхода последней выполненной команды, что совсем не то, что я ищу.

Есть ли легкие хаки для достижения того, что я am ищет?

Ответ 1

Если вы уверены, что статус будет только одной строкой, вы можете сделать что-то подобное с sed:

status=$(echo "$status" | sed -e 's:^foo$:bar:' -e 's:^baz$:buh:')

Вы также сможете получить что-то для работы с bash встроенной заменой. Это почти работает (я не знаю, как получить точное соответствие):

status=${status/foo/bar}
status=${status/baz/buh}

Если ваша цель состоит в том, чтобы быть более "функциональной" (и чтобы ваш код не был более опечатан), вы можете сделать это:

status=$(
  case "$status" in
    ("foo") echo "bar" ;;
    ("baz") echo "buh" ;;
    (*) echo "$status" ;;
  esac)

Хотя, честно говоря, bash, вероятно, один из худших языков, чтобы попробовать и быть функциональным. Он был действительно разработан с более императивным мышлением, о чем свидетельствует тот факт, что вы не можете легко составлять выражения. Посмотрите во втором фрагменте кода, как мне пришлось разбить его на два отдельных заявления? Если bash были разработаны для работы, вы могли бы написать что-то вроде этого:

status=${{status/baz/buh}/foo/bar}

Но это работает не.

Я предлагаю использовать только bash для более простых скриптов, а для более сложных вещей используйте что-то вроде Python или Ruby. Они позволят вам написать более функциональный код без необходимости постоянно бороться с языком.

Ответ 2

status="baz"
status=$(case $status in
  "foo") echo "bar" ;;
  "baz") echo "buh" ;;
  *) echo $status ;;
esac)
echo "status: $status"

Выход

$ ./shell.sh
status: buh

Ответ 3

Bash 4 имеет ассоциативные массивы:

# setup
unset vals i
indices=(foo baz)
val=(bar buh)
declare -A vals             # associative
for index in ${indices[@]}
do
    vals[$index]=${val[i++]}
done

$ # demos
$ status="foo"
$ status=${vals:-$status}
$ echo $status
bar
$ status="not found"
$ status=${vals:-$status}
$ echo $status
not found