Espansione dei parametri
La risposta ovvia è utilizzare una delle forme speciali di espansione dei parametri:
: ${STATE?"Need to set STATE"}
: ${DEST:?"Need to set DEST non-empty"}
O meglio (vedere la sezione "Posizione delle virgolette doppie" di seguito):
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
La prima variante (usando solo ?
) richiede che STATE sia impostato, ma STATE = "" (una stringa vuota) è OK - non esattamente quello che vuoi, ma l'alternativa e la notazione precedente.
La seconda variante (utilizzo :?
) richiede che DEST sia impostato e non vuoto.
Se non si fornisce alcun messaggio, la shell fornisce un messaggio predefinito.
Il ${var?}
costrutto è portatile alla versione 7 UNIX e Bourne Shell (1978 o successivi). Il ${var:?}
costrutto è leggermente più recente: penso che fosse in System III UNIX intorno al 1981, ma potrebbe essere stato in PWB UNIX prima. È quindi nella shell Korn e nelle shell POSIX, incluso in particolare Bash.
Di solito è documentato nella pagina man della shell in una sezione chiamata Parameter Expansion . Ad esempio, il bash
manuale dice:
${parameter:?word}
Visualizza errore se Null o Unset. Se il parametro è nullo o non impostato, l'espansione della parola (o un messaggio in tal senso se la parola non è presente) viene scritta nell'errore standard e la shell, se non è interattiva, viene chiusa. Altrimenti, viene sostituito il valore del parametro.
Il comando dei due punti
Dovrei probabilmente aggiungere che il comando due punti ha semplicemente valutato i suoi argomenti e poi ha esito positivo. È la notazione originale del commento della shell (prima di ' #
' alla fine della riga). Per molto tempo, gli script di shell Bourne avevano i due punti come primo carattere. La shell C leggeva una sceneggiatura e utilizzava il primo carattere per determinare se era per la shell C (un ' #
' hash) o la shell Bourne (un ' :
' due punti). Quindi il kernel è entrato in azione e ha aggiunto il supporto per ' #!/path/to/program
' e la shell Bourne ha ottenuto ' #
' commenti, e la convenzione del colon è andata avanti. Ma se ti imbatti in una sceneggiatura che inizia con due punti, ora saprai perché.
Posizione delle doppie virgolette
blong ha chiesto in un commento :
Qualche idea su questa discussione? https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749
L'essenza della discussione è:
... Tuttavia, quando lo faccio shellcheck
(con la versione 0.4.1), ottengo questo messaggio:
In script.sh line 13:
: ${FOO:?"The environment variable 'FOO' must be set and non-empty"}
^-- SC2086: Double quote to prevent globbing and word splitting.
Qualche consiglio su cosa dovrei fare in questo caso?
La risposta breve è "fai come shellcheck
suggerisce":
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
Per illustrare il motivo, studiare quanto segue. Nota che il :
comando non fa eco ai suoi argomenti (ma la shell valuta gli argomenti). Vogliamo vedere gli argomenti, quindi il codice seguente usa printf "%s\n"
al posto di :
.
$ mkdir junk
$ cd junk
$ > abc
$ > def
$ > ghi
$
$ x="*"
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
abc
def
ghi
$ unset x
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
bash: x: You must set x
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
bash: x: You must set x
$ x="*"
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
*
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
abc
def
ghi
$ x=
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$ unset x
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$
Si noti come il valore in $x
viene prima espanso *
e poi un elenco di nomi di file quando l'espressione complessiva non è tra virgolette. Questo è ciò che shellcheck
raccomanda dovrebbe essere risolto. Non ho verificato che non si oppone al modulo in cui l'espressione è racchiusa tra virgolette doppie, ma è ragionevole supporre che sarebbe OK.