2010-02-17 4 views
7

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

Так, в Баш можно было бы написать:

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

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

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

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

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

+0

вы просто желающие написать функцию? – thecoshman

+0

Если вы боитесь опечаток, используйте ['set -u'] (https://sipb.mit.edu/doc/safe-shell/) в начале вашей программы. – ceving

ответ

9

Если вы уверены, что статус будет только одна строка, вы могли бы сделать что-то подобное с СЕПГ:

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) 

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

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

Но что делает не работу.

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

+0

Способ не отвечать на вопрос и добавлять много нерелевантной информации. – mbac32768

+0

zsh позволит вам делать вложенные расширения параметров, как ваш последний пример. –

+9

@ mbac32768 Насколько я могу судить, я действительно отвечал на ваш вопрос, три раза на самом деле. Если вы не согласны, возможно, вам нужно изменить свой вопрос, или вы могли бы хотя бы объяснить, почему эти решения не работают для вас. Получение snarky, когда кто-то прилагает усилия, пытаясь помочь вам, немного хромает. –

-1

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 
+0

Действительно ли это так, как вы должны инициализировать ассоциативные массивы в bash4? –

+1

@Charles: Это один из способов, который подходит для этой демонстрации. Например, я мог бы использовать 'for index в foo baz' вместо использования массива. Или сделать прямое массовое задание или прочитать из файла. Что конкретно вы спрашиваете? –

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

выхода

$ ./shell.sh 
status: buh 
+1

Это третий фрагмент, который я опубликовал, но с ошибками синтаксиса. (Закрывает parens внутри '$ (...)' confuse bash, поэтому вам нужно использовать опциональный открытый паз для каждого случая.) –

+0

что вы имеете в виду путать bash? – ghostdog74

+0

ОК, я думаю, вы используете bash <4.0. В 4.0, я думаю, это исправлено. – ghostdog74