Assegnazione delle variabili al di fuori dell'istruzione case


8

In molte lingue è possibile assegnare il risultato di un'istruzione case / switch a una variabile, piuttosto che ripetere più volte l'assegnazione della variabile all'interno dell'istruzione case. È possibile fare qualcosa del genere nella shell Bash?

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

(O, a parte, in qualche altra conchiglia?)


Hai un extra (. Altrimenti, va bene.
HalosGhost

Risposte:


6

Il variable=$(...)costrutto prenderà l'output standard di qualunque comando sia presente $(...)e lo assegnerà a variable. Pertanto, per essere variableassegnato nel modo desiderato, i valori devono essere inviati all'output standard. Questo è facilmente eseguibile con il echocomando:

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

Funzionerà su bashtutte le altre shell POSIX.

Le parentesi sinistre opzionali

Secondo lo standard POSIX, le parentesi sinistre in caseun'istruzione sono opzionali e funzionano anche le seguenti:

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

Come sottolinea Gilles nei commenti, non tutte le shell accettano entrambe le forme in combinazione con $(...): per una tabella di compatibilità dettagliata in modo impressionante, vedere "$ ()" sostituzione comando vs. incorporato ")" .


Una pagina che ho controllato (non ricordo dove fosse) elencava l'apertura (come facoltativa. Ho pensato che potrebbe contribuire a evitare che l' )essere interpretata erroneamente come la chiusura )per l' $(...)espressione.
iconoclasta,

@iconoclast Sì. Le aperture (sono opzionali: il codice funziona allo stesso modo senza o senza di esse. Li ho lasciati solo perché, nel bene e nel male, questa è tradizione. La parte chiave della soluzione proposta è l'uso di echo.
Giovanni 1024

1
@iconoclast Le shell precedenti (pre-POSIX) non consentivano un'apertura (per i casepattern, ma alcune shell lo facevano e richiedevano l'apertura (quando caseveniva usata in una sostituzione di comando. Le conchiglie moderne vanno bene in entrambi i casi. Vedi in-ulm.de/~mascheck/various/cmd-subst
Gilles 'SO- smetti di essere malvagio'

1
@Gilles Grazie per queste informazioni. La profondità delle tue conoscenze è, come sempre, impressionante.
Giovanni 1024

2

color_code=$(…)assegna l'output del comando alla variabile color_code, con le nuove righe finali eliminate. Quindi è necessario produrre un output. Il codice che hai scritto tenta di essere eseguito 1come comando.

Puoi usare questo idioma. Nota che color_codesarà vuoto se $COLORnessuno dei valori supportati.

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

Ma non è molto idiomatico. Il linguaggio shell è orientato verso semplici combinazioni di semplici comandi. Questa grande sostituzione del comando è imbarazzante. La sostituzione del comando crea una subshell, che è più lenta del metodo semplice:

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

La principale differenza semantica tra i due approcci è che $(…)crea una subshell, in modo che qualsiasi assegnazione, uscita, reindirizzamento, ecc. Che viene eseguita all'interno non abbia alcun effetto all'esterno.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.