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 bashmanuale 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 shellchecksuggerisce":
: "${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 $xviene prima espanso *e poi un elenco di nomi di file quando l'espressione complessiva non è tra virgolette. Questo è ciò che shellcheckraccomanda 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.