Rozszerzenie parametru
Oczywistą odpowiedzią jest użycie jednej ze specjalnych form rozszerzania parametrów:
: ${STATE?"Need to set STATE"}
: ${DEST:?"Need to set DEST non-empty"}
Lub lepiej (patrz sekcja „Pozycja podwójnych cudzysłowów” poniżej):
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
Pierwszy wariant (używając just ?
) wymaga ustawienia STATE, ale STATE = "" (pusty ciąg znaków) jest OK - nie dokładnie to, czego chcesz, ale alternatywna i starsza notacja.
Drugi wariant (użycie :?
) wymaga ustawienia DEST i niepustego.
Jeśli nie podasz żadnego komunikatu, powłoka wyświetli komunikat domyślny.
${var?}
Konstrukt jest przenośny powrotem do Version 7 UNIX i Bourne Shell (1978) lub w jej pobliżu. ${var:?}
Konstrukt jest nieco nowsza: Myślę, że to było w systemie III UNIX około 1981, ale może to być w PWB UNIX wcześniej. Znajduje się zatem w powłoce Korna i powłokach POSIX, w tym szczególnie w Bash.
Zwykle jest to udokumentowane na stronie podręcznika powłoki w sekcji o nazwie Rozszerzenie parametru . Na przykład bash
instrukcja mówi:
${parameter:?word}
Błąd wyświetlania, jeśli Null lub Unset. Jeśli parametr ma wartość NULL lub jest nieustawiony, rozwinięcie słowa (lub komunikat o tym, jeśli słowo nie jest obecne) jest zapisywany do standardowego błędu i powłoka, jeśli nie jest interaktywna, kończy działanie. W przeciwnym razie wartość parametru zostanie podstawiona.
Komenda dwukropka
Powinienem chyba dodać, że polecenie dwukropka po prostu ocenia swoje argumenty, a następnie się udaje. Jest to oryginalna notacja komentarza powłoki (przed „ #
” do końca wiersza). Przez długi czas pierwsze skrypty skryptów Bourne'a miały dwukropek. Powłoka C czytałaby skrypt i używałaby pierwszego znaku, aby ustalić, czy chodzi o Powłokę C ( #
skrót), czy powłokę Bourne'a ( :
dwukropek). Następnie jądro wzięło udział w akcji i dodało wsparcie dla komentarzy, a #!/path/to/program
powłoka Bourne'a dostała #
komentarze, a konwencja okrężnicy poszła na marne. Ale jeśli natrafisz na skrypt rozpoczynający się dwukropkiem, teraz będziesz wiedział, dlaczego.
Pozycja podwójnych cytatów
blong zapytał w komentarzu :
Jakieś przemyślenia na temat tej dyskusji? https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749
Istotą dyskusji jest:
… Jednak kiedy shellcheck
to zrobię (w wersji 0.4.1), otrzymuję ten komunikat:
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.
Wszelkie porady dotyczące tego, co powinienem zrobić w tym przypadku?
Krótka odpowiedź brzmi „rób jak shellcheck
sugeruje”:
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
Aby zilustrować przyczynę, przestudiuj poniższe. Zauważ, że :
polecenie nie powtarza swoich argumentów (ale powłoka ocenia argumenty). Chcemy zobaczyć argumenty, więc poniższy kod używa printf "%s\n"
zamiast :
.
$ 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
$
Zwróć uwagę, w jaki sposób wartość in $x
jest rozwijana do najpierw, *
a następnie listy nazw plików, gdy ogólne wyrażenie nie jest w cudzysłowach. To, co shellcheck
zaleca, powinno zostać naprawione. Nie sprawdziłem, czy nie sprzeciwia się formie, w której wyrażenie jest ujęte w podwójne cudzysłowy, ale uzasadnione jest założenie, że byłoby OK.