2010-02-17 14 views
7

Ho individuato il bug di programmazione funzionale, quindi naturalmente non è più sufficiente per me. ;)istruzioni case bash valutano le stringhe

Così, in bash si potrebbe scrivere:

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

ma ho paura di errori di battitura, quindi mi piacerebbe preferiscono a scrivere:

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

La seconda forma è non valido poiché il caso valuta il codice di uscita dell'ultimo comando eseguito, che non è affatto quello che sto cercando.

Ci sono facili hack per ottenere quello che ho cercato ?

+0

stai semplicemente desideroso di scrivere una funzione? – thecoshman

+0

Se hai paura degli errori di battitura, usa ['set -u'] (https://sipb.mit.edu/doc/safe-shell/) all'inizio del tuo programma. – ceving

risposta

9

Se sei stato sicuro che sarà solo una linea, si potrebbe fare qualcosa di simile con sed:

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

Si può anche essere in grado di ottenere qualcosa su cui lavorare con la sostituzione built-in di bash. Questo quasi opere (non so di un modo per ottenere esattamente corrispondenti solo):

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

Se il vostro obiettivo è solo quello di essere più "funzionale" (e non per rendere il codice più typo-proof), si potrebbe fare questo:

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

anche se onestamente, bash è probabilmente una delle lingue peggiori per cercare di essere funzionale in e 'stato davvero progettato con una mentalità più imperativo, come dimostra il fatto che è possibile. facilmente comporre espressioni Vedi nel secondo snippet di codice come ho dovuto suddividerlo in due dichiarazioni separate? Se bash sono stati progettati per essere funzionale si sarebbe in grado di scrivere qualcosa di simile a questo, invece:

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

Ma questo non lavoro.

Suggerisco di usare bash solo per script più semplici e per cose più complicate usare qualcosa come Python o Ruby. Ti permetteranno di scrivere più codice funzionale senza dover costantemente lottare con la lingua.

+0

Modo per non rispondere alla domanda e aggiungere molte informazioni irrilevanti. – mbac32768

+0

zsh ti consentirà di eseguire espansioni di parametri nidificati come il tuo ultimo esempio. –

+9

@ mbac32768 per quanto posso dire di aver risposto alla tua domanda, tre volte in effetti. Se non sei d'accordo forse hai bisogno di riformulare la tua domanda, o almeno potresti spiegare perché queste soluzioni non funzionano per te. Essere irritati quando qualcuno si sforza di provare ad aiutarti è una specie di zoppo. –

-1

Bash 4 ha array associativi:

# 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

È così che dovresti inizializzare gli array associativi in ​​bash4? –

+1

@Charles: è un modo per espediente per questa demo. Ad esempio, avrei potuto fare 'for index in foo baz' invece di usare un array. O fatto un incarico diretto alla rinfusa o letto da un file. In particolare, di cosa stai chiedendo? –

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

uscita

$ ./shell.sh 
status: buh 
+1

Questo è il terzo snippet che ho postato, ma con errori di sintassi. (Gli parentesi ravvicinati all'interno di '$ (...)' confondono bash, quindi è necessario utilizzare il paren aperto opzionale su ciascun caso.) –

+0

cosa intendi confondere bash? – ghostdog74

+0

ok, penso che stai usando bash <4.0. In 4.0, penso che questo sia corretto. – ghostdog74

Problemi correlati