операторы bash преобразуются в строки - PullRequest
10 голосов
/ 17 февраля 2010

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

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

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

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

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

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

Есть ли простые способы достижения того, что я ищу ?

Ответы [ 3 ]

11 голосов
/ 17 февраля 2010

Если вы уверены, что статус будет состоять только из одной строки, вы можете сделать что-то подобное с помощью 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. Они позволят вам написать более функциональный код без необходимости постоянно бороться с языком.

3 голосов
/ 18 февраля 2010
status="baz"
status=$(case $status in
  "foo") echo "bar" ;;
  "baz") echo "buh" ;;
  *) echo $status ;;
esac)
echo "status: $status"

выход

$ ./shell.sh
status: buh
0 голосов
/ 17 февраля 2010

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
...