if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi.
Jens
210
Uwaga dla osób poszukujących rozwiązania: Istnieje wiele wysoko ocenianych odpowiedzi na to pytanie, które odpowiadają na pytanie „zmienna niepusta”. Więcej rozwiązań korekcyjnych („jest zestaw zmiennych”) wymieniono w odpowiedziach Jensa i Lionela poniżej.
Nathan Kidd
8
Również Russell Harmon i Seamus mają rację ze swoim -vtestem, chociaż wydaje się, że jest on dostępny tylko w nowych wersjach bashi nie jest przenośny między powłokami.
Graeme
5
Jak zauważył @NathanKidd, Lionel i Jens podają prawidłowe rozwiązania. prosseek, powinieneś zmienić zaakceptowaną odpowiedź na jedną z nich.
Garrett
3
... lub niepoprawna odpowiedź może zostać zanegowana przez bardziej wymagających wśród nas, ponieważ @prosseek nie rozwiązuje problemu.
dan3
Odpowiedzi:
2299
(Zwykle) Właściwy sposób
if[-z ${var+x}];then echo "var is unset";else echo "var is set to '$var'";fi
gdzie ${var+x}jest rozwinięciem parametru, który zwraca wartość do varzera, jeśli jest rozbrojony, i w xprzeciwnym razie zastępuje ciąg .
Cytaty Dygresja
Cytaty można pominąć (więc możemy powiedzieć ${var+x}zamiast "${var+x}"), ponieważ ta składnia i użycie gwarantuje, że rozwinie się tylko do czegoś, co nie wymaga cudzysłowów (ponieważ albo rozwija się do x(który nie zawiera podziałów słów, więc nie potrzebuje cudzysłowów), lub nic (co skutkuje [ -z ], co dogodnie daje taką samą wartość (prawda), [ -z "" ]co również).
Jednak chociaż cytaty można bezpiecznie pominąć i nie było to od razu oczywiste dla wszystkich (nie było nawet oczywiste dla pierwszego autora wyjaśnienia cytatów, który jest również głównym koderem Bash), czasem lepiej byłoby napisać rozwiązanie z cytatami, jak [ -z "${var+x}" ]przy bardzo niewielkim możliwym koszcie kary prędkości O (1). Pierwszy autor dodał również to jako komentarz obok kodu, używając tego rozwiązania, podając adres URL tej odpowiedzi, który teraz zawiera również wyjaśnienie, dlaczego cytaty można bezpiecznie pominąć.
(Często) Niewłaściwy sposób
if[-z "$var"];then echo "var is blank";else echo "var is set to '$var'";fi
Jest to często błędne, ponieważ nie rozróżnia zmiennej, która jest nieustawiona, a zmiennej, która jest ustawiona na pusty ciąg. To znaczy, jeśli var=''wtedy powyższe rozwiązanie wyświetli „var is blank”.
Rozróżnienie między nieustawionym a „ustawionym na pusty ciąg” jest niezbędne w sytuacjach, w których użytkownik musi określić rozszerzenie lub dodatkową listę właściwości, a nieokreślenie ich domyślnie przyjmuje niepustą wartość, podczas gdy określenie pustego ciągu powinno spraw, aby skrypt używał pustego rozszerzenia lub listy dodatkowych właściwości.
To rozróżnienie może nie być konieczne w każdym scenariuszu. W takich przypadkach [ -z "$var" ]będzie dobrze.
@Garrett, twoja edycja spowodowała, że ta odpowiedź jest niepoprawna, ${var+x}to poprawne zastąpienie do użycia. Użycie [ -z ${var:+x} ]nie daje innego wyniku niż [ -z "$var" ].
Graeme
11
To nie działa Otrzymuję komunikat „nieustawione” niezależnie od tego, czy zmienna jest ustawiona na wartość, czy nie (wyczyszczone przez „unset var”, „echo $ var” nie generuje danych wyjściowych).
Brent212,
10
W przypadku składni rozwiązania $ {parametr + słowo} oficjalna sekcja podręcznika to gnu.org/software/bash/manual/… ; jednak błąd w tym, że nie bardzo wyraźnie wspomina o tej składni, ale mówi tylko cytat (Pominięcie dwukropka [":"] powoduje test tylko dla parametru, który nie jest ustawiony. .. $ {parametr: + słowo} [oznacza] Jeśli parametr jest zerowy lub nieustawiony, nic nie jest podstawiane, w przeciwnym razie rozszerzenie wyrazu jest podstawiane.); cytowany odnośnik pubs.opengroup.org/onlinepubs/9699919799/utilities/... (dobrze wiedzieć) ma tutaj znacznie jaśniejsze dokumenty.
Destiny Architect
7
Wygląda na to, że cytaty są wymagane, gdy używasz wielu wyrażeń, np [ -z "" -a -z ${var+x} ] Dostaje się bash: [: argument expecteddo bash 4.3-ubuntu (ale nie np. Zsh). Naprawdę nie lubię odpowiedzi, używając składni, która w niektórych przypadkach działa.
FauxFaux,
41
Użycie prostego [ -z $var ]nie jest bardziej „błędne” niż pominięcie cudzysłowu. Tak czy inaczej, przyjmujesz założenia dotyczące wkładu. Jeśli dobrze traktujesz pusty ciąg jako nieuzbrojony, [ -z $var ]wystarczy.
nshew
909
Aby sprawdzić zmienną łańcuchową o wartości innej niż zero / zero, tj. Jeśli jest ustawiona, użyj
if[-n "$1"]
To jest przeciwieństwo -z. Używam -nwięcej niż -z.
Użyłbyś tego w następujący sposób:
if[-n "$1"];then
echo "You supplied the first parameter!"else
echo "First parameter not supplied."fi
Zwykle wolę [[ ]]ponad [ ], ponieważ [[ ]]jest bardziej wydajny i powoduje mniej problemów w niektórych sytuacjach (zobacz to pytanie, aby wyjaśnić różnicę między nimi). Pytanie dotyczy w szczególności rozwiązania bash i nie wspomina o żadnych wymaganiach dotyczących przenośności.
Flow
18
Pytanie brzmi, jak sprawdzić, czy zmienna jest ustawiona . Wtedy nie możesz założyć, że zmienna jest ustawiona.
HelloGoodbye,
7
Zgadzam się, []działa lepiej zwłaszcza w przypadku skryptów powłoki (non-bash).
Hengjie
73
Nie działa set -u.
Ciro Santilli 10 病毒 审查 六四 事件 法轮功
63
Pamiętaj, że -njest to test domyślny, więc prościej [ "$1" ]lub [[ $1 ]]też działaj. Należy również pamiętać, że przy [[ ]]cytowaniu nie jest konieczne .
tne
478
Oto jak sprawdzić, czy parametr jest nieustawiony , pusty („Null”) lub ustawiony za pomocą wartości :
+--------------------+----------------------+-----------------+-----------------+|Expression| parameter | parameter | parameter ||in script:|Set and NotNull|SetButNull|Unset|+--------------------+----------------------+-----------------+-----------------+| ${parameter:-word}| substitute parameter | substitute word | substitute word || ${parameter-word}| substitute parameter | substitute null | substitute word || ${parameter:=word}| substitute parameter | assign word | assign word || ${parameter=word}| substitute parameter | substitute null | assign word || ${parameter:?word}| substitute parameter | error, exit | error, exit || ${parameter?word}| substitute parameter | substitute null | error, exit || ${parameter:+word}| substitute word | substitute null | substitute null || ${parameter+word}| substitute word | substitute word | substitute null |+--------------------+----------------------+-----------------+-----------------+
We wszystkich przypadkach pokazanych jako „podstawienie” wyrażenie jest zastępowane pokazaną wartością. We wszystkich przypadkach pokazanych jako „przypisać” parametrowi przypisywana jest ta wartość, która również zastępuje wyrażenie.
Aby pokazać to w akcji:
+--------------------+----------------------+-----------------+-----------------+|Expression| FOO="world"| FOO=""| unset FOO ||in script:|(Set and NotNull)|(SetButNull)|(Unset)|+--------------------+----------------------+-----------------+-----------------+| ${FOO:-hello}| world | hello | hello || ${FOO-hello}| world |""| hello || ${FOO:=hello}| world | FOO=hello | FOO=hello || ${FOO=hello}| world |""| FOO=hello || ${FOO:?hello}| world | error, exit | error, exit || ${FOO?hello}| world |""| error, exit || ${FOO:+hello}| hello |""|""|| ${FOO+hello}| hello | hello |""|+--------------------+----------------------+-----------------+-----------------+
@HelloGoodbye Tak to działa: set foo; echo ${1:-set but null or unset}echos "foo"; set --; echo ${1:-set but null or unset}echa ustawione, ale zerowe ...
Jens
4
@HelloGoodbye pozycyjne parametry można ustawić, uh, set:-)
Jens
95
Ta odpowiedź jest bardzo myląca. Jakieś praktyczne przykłady korzystania z tego stołu?
Ben Davis,
12
@BenDavis Szczegóły wyjaśniono w linku do standardu POSIX, który odwołuje się do rozdziału, z którego pochodzi tabela. Jedną z konstrukcji, których używam w prawie każdym skrypcie, który piszę, jest : ${FOOBAR:=/etc/foobar.conf}ustawienie domyślnej wartości zmiennej, jeśli jest ona nieustawiona lub zerowa.
Jens
1
parameterto dowolna nazwa zmiennej. wordto ciąg znaków, który należy zastąpić w zależności od używanej składni w tabeli i tego, czy zmienna $parameterjest ustawiona, ustawiona, ale pusta, czy też nie. Nie komplikuje to, ale wordmoże również zawierać zmienne! Może to być bardzo przydatne do przekazywania opcjonalnych argumentów oddzielonych znakiem. Na przykład: ${parameter:+,${parameter}}wyświetla przecinek oddzielony, ,$parameterjeśli jest ustawiony, ale nie ma wartości null. W tym przypadku wordjest,${parameter}
TrinitronX
260
Chociaż większość podanych tu technik jest poprawna, bash 4.2 obsługuje rzeczywisty test na obecność zmiennej ( man bash ), zamiast testować wartość zmiennej.
Warto zauważyć, że to podejście nie spowoduje błędu, gdy zostanie użyte do sprawdzenia, czy zmienna nie jest ustawiona w trybie set -u/ set -o nounset, w przeciwieństwie do wielu innych podejść, takich jak używanie [ -z.
W wersji bash 4.1.2, niezależnie od tego, czy zmienna jest ustawiona, [[ -v aaa ]]; echo $?==>-bash: conditional binary operator expected-bash: syntax error near 'aaa'
Dan
32
Argument „-v” do wbudowanego „testu” został dodany w bash 4.2.
Ti Strga
19
argument -v został dodany jako uzupełnienie opcji powłoki -u (rzeczownik). Przy włączonym 'rzeczowniku' (set -u) powłoka zwróci błąd i zakończy działanie, jeśli nie będzie interaktywna. $ # było dobre do sprawdzania parametrów pozycyjnych. Jednak nazwane zmienne potrzebowały innego sposobu, niż clobbering, aby zidentyfikować je jako nieustawione. To niefortunne, że ta funkcja pojawiła się tak późno, ponieważ wielu z nich musi być kompatybilnych z wcześniejszymi wersjami, w którym to przypadku nie mogą jej używać. Jedyną inną opcją jest użycie sztuczek lub „hacków”, aby obejść to, jak pokazano powyżej, ale jest to najbardziej nieeleganckie.
osirisgothra
2
Zauważ, że to nie działa dla zmiennych, które są zadeklarowane, ale nie są ustawione. np.declare -a foo
miken32
17
Dlatego wciąż czytam po odpowiedzi zaakceptowanej / najwyżej głosowanej.
Joe
176
Można to zrobić na wiele sposobów, jednym z nich jest:
if[-z "$1"]
To się powiedzie, jeśli 1 $ jest zerowy lub nieustawiony
Istnieje różnica między parametrem nieustawionym a parametrem o wartości zerowej.
chepner
21
Chcę tylko być pedantyczny i wskazać, że jest to odpowiedź przeciwna do tego, co stawia pytanie. Pytania dotyczą tego, czy zmienna JEST ustawiona, a nie, czy zmienna nie jest ustawiona.
Philluminati,
47
[[ ]]jest niczym innym jak pułapką przenośności. if [ -n "$1" ]należy go tutaj użyć.
Jens
73
Ta odpowiedź jest niepoprawna. Pytanie dotyczy sposobu ustalenia, czy zmienna jest ustawiona, a nie czy jest ustawiona na niepustą wartość. Biorąc pod uwagę foo="", $fooma wartość, ale -zpo prostu zgłosi, że jest pusta. I -z $foowybuchnie, jeśli masz set -o nounset.
Keith Thompson,
4
Zależy to od definicji „ustawiona zmienna”. Jeśli chcesz sprawdzić, czy zmienna jest ustawiona na niezerowy ciąg, odpowiedź mbranning jest poprawna. Ale jeśli chcesz sprawdzić, czy zmienna jest zadeklarowana, ale nie zainicjowana (tj. foo=), To odpowiedź Russela jest poprawna.
Flow
76
Zawsze znajduję tabelę POSIX w drugiej odpowiedzi wolną od grokowania, więc oto moje zdanie:
Zauważ, że każda grupa (z poprzedzającym dwukropkiem i bez niego) ma takie same ustawione i nieuzbrojone przypadki, więc jedyną różnicą jest sposób obsługi pustych przypadków.
W poprzednim dwukropku puste i nieuzbrojone przypadki są identyczne, więc użyłbym tych tam, gdzie to możliwe (tj. Używałbym :=nie tylko =, ponieważ pusty przypadek jest niespójny).
Nagłówki:
zestaw oznacza, że VARIABLEnie jest pusty ( VARIABLE="something")
puste oznacza, że VARIABLEjest puste / null ( VARIABLE="")
unset oznacza, VARIABLEże nie istnieje ( unset VARIABLE)
Wartości:
$VARIABLE oznacza, że wynikiem jest pierwotna wartość zmiennej.
"default" oznacza, że wynikiem był podany ciąg zastępczy.
"" oznacza, że wynik ma wartość NULL (pusty ciąg).
exit 127 oznacza, że skrypt przestaje działać z kodem wyjścia 127.
$(VARIABLE="default")oznacza, że wynikiem jest oryginalna wartość zmiennej, a podany ciąg zastępujący jest przypisywany do zmiennej do wykorzystania w przyszłości.
Naprawiono tylko te, które są rzeczywistymi błędami kodowania (przypadki niepożądanej pośredniczości podczas pracy ze zmiennymi). Dokonałem edycji, aby naprawić kilka innych przypadków, w których dolar robi różnicę w interpretacji opisu. BTW, wszystkie zmienne powłoki (z wyjątkiem tablic) są zmiennymi łańcuchowymi; może się zdarzyć, że zawierają ciąg, który można interpretować jako liczbę. Mówienie o ciągach tylko zamienia komunikat. Cytaty nie mają nic wspólnego z ciągami, są tylko alternatywą dla ucieczki. VARIABLE=""można zapisać jako VARIABLE=. Mimo to ten pierwszy jest bardziej czytelny.
Palec
Dzięki za tabelę jest bardzo przydatna, ale staram się, aby skrypt zakończył działanie, jeśli jest rozbrojony lub pusty. Ale kod wyjścia, który otrzymuję, to 1, a nie 127.
Astronauta
64
Aby zobaczyć, czy zmienna nie jest pusta, używam
if[[ $var ]];then...# `$var' expands to a nonempty string
Odwrotny test sprawdza, czy zmienna jest rozbrojona lub pusta:
if[[! $var ]];then...# `$var' expands to the empty string (set or not)
Aby sprawdzić, czy zmienna jest ustawiona (pusta czy niepusta), używam
if[[ ${var+x}]];then...# `var' exists (empty or nonempty)if[[ ${1+x}]];then...# Parameter 1 exists (empty or nonempty)
Przeciwnie, jeśli zmienna jest rozbrojona:
if[[! ${var+x}]];then...# `var' is not set at allif[[! ${1+x}]];then...# We were called with no arguments
Ja także używałem tego od dłuższego czasu; tylko w mniejszym stopniu:[ $isMac ] && param="--enable-shared"
@Bhaskar Myślę, że dzieje się tak, ponieważ ta odpowiedź już podała w zasadzie tę samą odpowiedź ( ustawiono opcję ${variable+x}uzyskiwania xiff $variable) prawie pół roku wcześniej. Ma też znacznie więcej szczegółów wyjaśniających, dlaczego tak jest.
Mark Haferkamp
ale ${variable+x}jest mniej czytelny (i oczywisty)
Knocte
35
W nowoczesnej wersji Bash (chyba 4.2 lub nowszej; nie wiem na pewno), spróbowałbym:
if[!-v SOMEVARIABLE ]#note the lack of a $ sigilthen
echo "Variable is unset"elif[-z "$SOMEVARIABLE"]then
echo "Variable is set to an empty string"else
echo "Variable is set to some string"fi
Zauważ też, że [ -v "$VARNAME" ]nie jest to niepoprawne, ale po prostu wykonuje inny test. Załóżmy VARNAME=foo; następnie sprawdza, czy jest ustawiona zmienna o nazwie foo.
chepner
5
Uwaga dla tych, którzy chcą -vmieć przenośność, nie jest zgodny z POSIX
kzh
Jeśli się dostanie [: -v: unexpected operator, trzeba zapewnić, aby użyć bashzamiast sh.
koppor
25
if["$1"!=""];then
echo \$1 is setelse
echo \$1 is not setfi
Chociaż w przypadku argumentów zwykle najlepiej jest przetestować $ #, czyli, moim zdaniem, liczbę argumentów.
if[ $# -gt 0 ]; then
echo \$1 is setelse
echo \$1 is not setfi
Pierwszy test jest wstecz; Myślę, że chcesz [ "$1" != "" ](lub [ -n "$1" ]) ...
Gordon Davisson
10
Nie powiedzie się, jeśli $1zostanie ustawiony pusty ciąg.
HelloGoodbye
2
Druga część odpowiedzi (parametry zliczania) jest użytecznym obejściem dla pierwszej części odpowiedzi, która nie działa, gdy $1jest ustawiona na pusty ciąg.
Mark Berry
To się nie powiedzie, jeśli set -o nounsetjest włączone.
Flimm
21
Uwaga
Daję odpowiedź bardzo skoncentrowaną na Bash z powodu bashtagu.
Krótka odpowiedź
Tak długo, jak masz do czynienia z nazwanymi zmiennymi w Bash, ta funkcja powinna zawsze informować, czy zmienna została ustawiona, nawet jeśli jest to pusta tablica.
variable-is-set(){
declare -p "$1"&>/dev/null
}
Dlaczego to działa
W Bash (przynajmniej do 3.0), jeśli varjest zmienną zadeklarowaną / ustawioną, wówczas declare -p varwypisuje declarepolecenie, które ustawi zmienną varna dowolny jej aktualny typ i wartość, i zwraca kod statusu 0(sukces). Jeśli nie varjest zadeklarowany, declare -p varwyświetla komunikat o błędzie stderri zwraca kod stanu 1. Użycie &>/dev/nullprzekierowuje zarówno zwykłe, jak stdouti stderrwyjściowe /dev/null, nigdy nie widoczne i bez zmiany kodu statusu. Dlatego funkcja zwraca tylko kod statusu.
Dlaczego inne metody (czasami) zawodzą w Bash
[ -n "$var" ]: Sprawdza tylko, czy ${var[0]}jest niepuste. (W Bash $varjest taki sam jak ${var[0]}.)
[ -n "${var+x}" ]: To sprawdza tylko, czy ${var[0]}jest ustawione.
[ "${#var[@]}" != 0 ]: Sprawdza to tylko, czy $varustawiony jest przynajmniej jeden indeks .
Gdy ta metoda zawiedzie w Bash
To działa tylko dla nazwanych zmiennych (włącznie $_) nie pewnych zmiennych specjalnych ( $!, $@, $#, $$, $*, $?, $-, $0, $1, $2, ..., a wszelkie mogę zapomnieć). Ponieważ żadna z nich nie jest tablicami, styl POSIX [ -n "${var+x}" ]działa dla wszystkich tych zmiennych specjalnych. Ale uważaj na zawijanie go w funkcję, ponieważ wiele specjalnych zmiennych zmienia wartości / istnienie podczas wywoływania funkcji.
Uwaga dotycząca zgodności z powłoką
Jeśli twój skrypt ma tablice i próbujesz uczynić go kompatybilnym z jak największą liczbą powłok, rozważ użycie typeset -pzamiast niego declare -p. Czytałem, że ksh obsługuje tylko te pierwsze, ale nie byłem w stanie tego przetestować. Wiem, że Bash 3.0+ i Zsh 5.5.1 obsługują oba typeset -pi declare -próżnią się tylko tym, w którym jedno jest alternatywą dla drugiego. Ale nie testowałem różnic poza tymi dwoma słowami kluczowymi i nie testowałem innych powłok.
Jeśli potrzebujesz, aby skrypt był zgodny z POSIX sh, nie możesz używać tablic. Bez tablic [ -n "{$var+x}" ]działa.
Kod porównawczy dla różnych metod w Bash
Ta funkcja resetuje zmienną var, evals przekazany kod, uruchamia testy w celu ustalenia, czy varjest ustawiona przez evalkod d, a na koniec wyświetla wynikowe kody stanu dla różnych testów.
Ja omijając test -v var, [ -v var ]i [[ -v var ]]ponieważ dają one takie same wyniki ze standardem POSIX [ -n "${var+x}" ], wymagając Basha wersji 4.2 lub nowszej. Pomijam również, typeset -pponieważ jest taki sam, jak declare -pw testowanych przeze mnie powłokach (Bash 3.0 do 5.0 i Zsh 5.5.1).
is-var-set-after(){# Set var by passed expression.
unset var
eval"$1"# Run the tests, in increasing order of accuracy.[-n "$var"]# (index 0 of) var is nonempty
nonempty=$?[-n "${var+x}"]# (index 0 of) var is set, maybe empty
plus=$?["${#var[@]}"!=0]# var has at least one index set, maybe empty
count=$?
declare -p var &>/dev/null # var has been declared (any type)
declared=$?# Show test results.
printf '%30s: %2s %2s %2s %2s\n'"$1" $nonempty $plus $count $declared
}
Kod przypadku testowego
Zauważ, że wyniki testu mogą być nieoczekiwane z powodu traktowania przez Bash indeksów tablic nienumerycznych jako „0”, jeśli zmienna nie została zadeklarowana jako tablica asocjacyjna. Również tablice asocjacyjne działają tylko w Bash 4.0+.
# Header.
printf '%30s: %2s %2s %2s %2s\n'"test"'-n''+x''#@''-p'# First 5 tests: Equivalent to setting 'var=foo' because index 0 of an# indexed array is also the nonindexed value, and non-numerical# indices in an array not declared as associative are the same as# index 0.
is-var-set-after "var=foo"# 0 0 0 0
is-var-set-after "var=(foo)"# 0 0 0 0
is-var-set-after "var=([0]=foo)"# 0 0 0 0
is-var-set-after "var=([x]=foo)"# 0 0 0 0
is-var-set-after "var=([y]=bar [x]=foo)"# 0 0 0 0# '[ -n "$var" ]' fails when var is empty.
is-var-set-after "var=''"# 1 0 0 0
is-var-set-after "var=([0]='')"# 1 0 0 0# Indices other than 0 are not detected by '[ -n "$var" ]' or by# '[ -n "${var+x}" ]'.
is-var-set-after "var=([1]='')"# 1 1 0 0
is-var-set-after "var=([1]=foo)"# 1 1 0 0
is-var-set-after "declare -A var; var=([x]=foo)"# 1 1 0 0# Empty arrays are only detected by 'declare -p'.
is-var-set-after "var=()"# 1 1 1 0
is-var-set-after "declare -a var"# 1 1 1 0
is-var-set-after "declare -A var"# 1 1 1 0# If 'var' is unset, then it even fails the 'declare -p var' test.
is-var-set-after "unset var"# 1 1 1 1
Wyjście testowe
W mnemoniki badań odpowiadają w wierszu nagłówka, aby [ -n "$var" ], [ -n "${var+x}" ], [ "${#var[@]}" != 0 ]i declare -p var, odpowiednio.
declare -p var &>/dev/null jest (100%?) niezawodny do testowania nazwanych zmiennych w Bash od co najmniej 3.0.
[ -n "${var+x}" ] jest niezawodny w sytuacjach zgodnych z POSIX, ale nie obsługuje tablic.
Istnieją inne testy do sprawdzania, czy zmienna nie jest pusta, oraz do sprawdzania deklarowanych zmiennych w innych powłokach. Ale testy te nie są odpowiednie dla skryptów Bash ani POSIX.
Z odpowiedzi, które próbowałem, ta ( declare -p var &>/dev/null) jest TYLKO tą, która działa. DZIĘKUJĘ CI!
user1387866
2
@ mark-haferkamp Próbowałem edytować twoją odpowiedź, aby dodać krytyczne poprzedzające „/” do kodu funkcji, więc czyta, ... &> /dev/nullale SO nie pozwala mi na edycję pojedynczego znaku 🙄 (musi być> 6 znaków - nawet próbowałem dodać białe znaki ale to nie działało). Warto również zmienić funkcję, aby przełączyć się $1na próbkę o nazwie zmienna (np. OUTPUT_DIR), Ponieważ, jak zauważyłeś, specjalne zmienne, takie jak $1, nie działają tutaj. W każdym razie jest to zmiana krytyczna, w przeciwnym razie kod chce utworzyć plik o nazwie nullw katalogu względnym o nazwie dev. BTW - świetna odpowiedź!
JoeHanna
Działa także użycie nazwy zmiennej bez przedrostka $: declare -p PATH &> /dev/nullzwraca 0, gdzie declare -p ASDFASDGFASKDF &> /dev/nullzwraca 1. 1. (w wersji bash 5.0.11 (1))
joehanna
1
Świetna robota! 1 słowo przestrogi: declare vardeklaruje zmienną var, ale nie ustawia jej pod względem set -o nounset: Testuj za pomocądeclare foo bar=; set -o nounset; echo $bar; echo $foo
xebeche
@joehanna Dzięki za złapanie tego zaginionego /! Naprawiłem to, ale myślę, że logika jest wystarczająco myląca, aby uzasadnić działanie funkcji, szczególnie w świetle komentarza @ xebeche. @ xebeche To jest niewygodne dla mojej odpowiedzi… Wygląda na to, że będę musiał spróbować czegoś takiego jak declare -p "$1" | grep =lub test -v "$1".
Mark Haferkamp
19
Dla tych, którzy chcą sprawdzić, czy nie jest ustawiony lub pusty w skrypcie z set -u:
if[-z "${var-}"];then
echo "Must provide var environment variable. Exiting...."
exit 1fi
Regularne [ -z "$var" ]sprawdzanie zakończy się niepowodzeniem z var; unbound variableif, set -uale [ -z "${var-}" ]rozwija się do pustego łańcucha, jeśli varjest rozbrojony bez niepowodzenia.
Brakuje dwukropka. To powinno być ${var:-}, nie ${var-}. Ale w Bash mogę potwierdzić, że działa nawet bez dwukropka.
Palec
3
${var:-}i ${var-}oznaczają różne rzeczy. ${var:-}rozwinie się do pustego ciągu, jeśli jest varrozbrojony lub zerowy, i ${var-}rozwinie się do pustego ciągu, tylko jeśli zostanie rozbrojony.
RubenLaguna
Właśnie nauczyłem się czegoś nowego, dzięki! Pominięcie dwukropka powoduje tylko test parametru, który nie jest ustawiony. Innymi słowy, jeśli dwukropek jest uwzględniony, operator sprawdza istnienie obu parametrów i czy jego wartość nie jest zerowa; jeśli dwukropek zostanie pominięty, operator sprawdza tylko istnienie. Tutaj nie ma znaczenia, ale dobrze wiedzieć.
Palec
17
Chcesz wyjść, jeśli jest rozbrojony
To zadziałało dla mnie. Chciałem, aby mój skrypt zakończył działanie z komunikatem o błędzie, jeśli parametr nie został ustawiony.
#!/usr/bin/env bashset-o errexit
# Get the value and empty validation check all in one
VER="${1:?You must pass a version of the format 0.0.0 as the only argument}"
Zwraca to z błędem po uruchomieniu
peek@peek:~$ ./setver.sh
./setver.sh: line 13:1:You must pass a version of the format 0.0.0 as the only argument
Zaznacz tylko, bez wyjścia - puste i rozbrojone są NIEPRAWIDŁOWE
Wypróbuj tę opcję, jeśli chcesz tylko sprawdzić, czy wartość set = VALID lub unset / empty = INVALID.
Aby sprawdzić, czy zmienna jest ustawiona na niepustą wartość, użyj [ -n "$x" ], jak wskazali już inni.
Przez większość czasu dobrym pomysłem jest traktowanie zmiennej, która ma pustą wartość w ten sam sposób, jak zmiennej, która jest nieuzbrojona. Ale możesz je rozróżnić, jeśli potrzebujesz: [ -n "${x+set}" ]( "${x+set}"rozwija się do setif xjest ustawiony i do pustego ciągu jeśli xjest nieustawiony).
Aby sprawdzić, czy parametr został przekazany, przetestuj $#, czyli liczbę parametrów przekazanych do funkcji (lub do skryptu, gdy nie ma jej w funkcji) (patrz odpowiedź Paula ).
Przeczytaj sekcję „Rozszerzanie parametrów” na bashstronie man. Rozszerzanie parametrów nie zapewnia ogólnego testu dla ustawianej zmiennej, ale istnieje kilka rzeczy, które można zrobić z parametrem, jeśli nie jest ustawiony.
Na przykład:
function a {
first_arg=${1-foo}# rest of the function}
ustawi wartość first_argrówną, $1jeśli jest przypisany, w przeciwnym razie użyje wartości „foo”. Jeśli aabsolutnie konieczne jest przyjęcie pojedynczego parametru i nie istnieje żaden dobry parametr domyślny, można wyjść z komunikatem o błędzie, gdy nie podano żadnego parametru:
function a {: ${1?a must take a single argument}# rest of the function}
(Zwróć uwagę na użycie :jako polecenia zerowego, które po prostu rozszerza wartości jego argumentów. Nie chcemy nic robić $1w tym przykładzie, po prostu wyjdź, jeśli nie jest ustawione)
Użycie [[ -z "$var" ]]jest najłatwiejszym sposobem na sprawdzenie, czy zmienna została ustawiona, czy nie, ale ta opcja -znie rozróżnia zmiennej nieuzbrojonej od zmiennej ustawionej na pusty ciąg:
Powyższe odpowiedzi nie działają, gdy set -uwłączona jest opcja Bash . Nie są też dynamiczne, np. Jak testować zmienną o nazwie „manekin” jest zdefiniowany? Spróbuj tego:
is_var_defined(){if[ $# -ne 1 ]then
echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
exit 1fi# Tricky. Since Bash option 'set -u' may be enabled, we cannot directly test if a variable# is defined with this construct: [ ! -z "$var" ]. Instead, we must use default value# substitution with this construct: [ ! -z "${var:-}" ]. Normally, a default value follows the# operator ':-', but here we leave it blank for empty (null) string. Finally, we need to# substitute the text from $1 as 'var'. This is not allowed directly in Bash with this# construct: [ ! -z "${$1:-}" ]. We need to use indirection with eval operator.# Example: $1="var"# Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]"# Code execute: [ ! -z ${var:-} ]eval"[ ! -z \${$1:-} ]"return $?# Pedantic.}
if[[ ${1:+isset}]]then echo "It was set and not null.">&2else echo "It was not set or it was null.">&2fiif[[ ${1+isset}]]then echo "It was set but might be null.">&2else echo "It was was not set.">&2fi
Witamy w StackOverflow. Doceniając twoją odpowiedź, najlepiej podać więcej niż tylko kod. Czy możesz dodać uzasadnienie do swojej odpowiedzi lub małe wyjaśnienie? Zobacz tę stronę, aby uzyskać inne pomysły na rozszerzenie odpowiedzi.
Celeo
0
Tego używam na co dzień:
## Check if a variable is set# param1 name of the variable#function is_set(){[[-n "${1}"]]&& test -n "$(eval "echo "\${${1}+x}"")"}
Działa to dobrze w systemach Linux i Solaris aż do wersji bash 3.0.
Od wersji Bash 2.0+ Pośrednie rozszerzenie jest dostępne. Możesz zastąpić długi i skomplikowany (wraz z eval) test -n "$(eval "echo "\${${1}+x}"")"również ekwiwalentem:[[ ${!1+x} ]]
0
Lubię funkcje pomocnicze, aby ukryć prymitywne szczegóły bash. W takim przypadku powoduje to jeszcze więcej (ukrytego) chamstwa:
# The first ! negates the result (can't use -n to achieve this)# the second ! expands the content of varname (can't do ${$varname})functionIsDeclared_Tricky{local varname="$1"![-z ${!varname+x}]}
Ponieważ po raz pierwszy miałem błędy w tej implementacji (zainspirowane odpowiedziami Jensa i Lionela), wpadłem na inne rozwiązanie:
# Ask for the properties of the variable - fails if not declaredfunctionIsDeclared(){
declare -p $1 &>/dev/null
}
Uważam, że jest bardziej bezpośredni, bardziej wstydliwy i łatwiejszy do zrozumienia / zapamiętania. Przypadek testowy pokazuje, że jest równoważny:
function main(){
declare -i xyz
local foo
local bar=local baz=''IsDeclared_Tricky xyz; echo "IsDeclared_Tricky xyz: $?"IsDeclared_Tricky foo; echo "IsDeclared_Tricky foo: $?"IsDeclared_Tricky bar; echo "IsDeclared_Tricky bar: $?"IsDeclared_Tricky baz; echo "IsDeclared_Tricky baz: $?"IsDeclared xyz; echo "IsDeclared xyz: $?"IsDeclared foo; echo "IsDeclared foo: $?"IsDeclared bar; echo "IsDeclared bar: $?"IsDeclared baz; echo "IsDeclared baz: $?"}
main
Przypadek testowy także pokazuje, że local varma nie deklarują var (o ile nie następuje „=”). Od dłuższego czasu myślałem, że zadeklarowałem zmienne w ten sposób, aby odkryć teraz, że po prostu wyraziłem zamiar ... Chyba nie można tego zrobić.
Myślę, że masz na myśli set -o nounset, nie set -o noun set. Działa to tylko dla edytowanych zmiennych export. Zmienia również ustawienia w sposób, którego cofnięcie jest niewygodne.
Keith Thompson,
-1
Zawsze używam tego, ponieważ wydaje się łatwy do zrozumienia dla każdego, kto zobaczy kod po raz pierwszy:
if["$variable"=""]then
echo "Variable X is empty"fi
A jeśli chcesz sprawdzić, czy nie pusty;
if[!"$variable"=""]then
echo "Variable X is not empty"fi
Pytanie dotyczy sposobu sprawdzenia, czy zmienna jest ustawiona, a nie, czy zmienna jest pusta.
HelloGoodbye
Prawdopodobnie musisz użyć [[ ... ]]zamiast [ ... ]. To ostatnie jest w rzeczywistości zewnętrznym poleceniem i nie miałoby żadnego wglądu w to, czy zmienna jest ustawiona, czy nie.
if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi
.-v
testem, chociaż wydaje się, że jest on dostępny tylko w nowych wersjachbash
i nie jest przenośny między powłokami.Odpowiedzi:
(Zwykle) Właściwy sposób
gdzie
${var+x}
jest rozwinięciem parametru, który zwraca wartość dovar
zera, jeśli jest rozbrojony, i wx
przeciwnym razie zastępuje ciąg .Cytaty Dygresja
Cytaty można pominąć (więc możemy powiedzieć
${var+x}
zamiast"${var+x}"
), ponieważ ta składnia i użycie gwarantuje, że rozwinie się tylko do czegoś, co nie wymaga cudzysłowów (ponieważ albo rozwija się dox
(który nie zawiera podziałów słów, więc nie potrzebuje cudzysłowów), lub nic (co skutkuje[ -z ]
, co dogodnie daje taką samą wartość (prawda),[ -z "" ]
co również).Jednak chociaż cytaty można bezpiecznie pominąć i nie było to od razu oczywiste dla wszystkich (nie było nawet oczywiste dla pierwszego autora wyjaśnienia cytatów, który jest również głównym koderem Bash), czasem lepiej byłoby napisać rozwiązanie z cytatami, jak
[ -z "${var+x}" ]
przy bardzo niewielkim możliwym koszcie kary prędkości O (1). Pierwszy autor dodał również to jako komentarz obok kodu, używając tego rozwiązania, podając adres URL tej odpowiedzi, który teraz zawiera również wyjaśnienie, dlaczego cytaty można bezpiecznie pominąć.(Często) Niewłaściwy sposób
Jest to często błędne, ponieważ nie rozróżnia zmiennej, która jest nieustawiona, a zmiennej, która jest ustawiona na pusty ciąg. To znaczy, jeśli
var=''
wtedy powyższe rozwiązanie wyświetli „var is blank”.Rozróżnienie między nieustawionym a „ustawionym na pusty ciąg” jest niezbędne w sytuacjach, w których użytkownik musi określić rozszerzenie lub dodatkową listę właściwości, a nieokreślenie ich domyślnie przyjmuje niepustą wartość, podczas gdy określenie pustego ciągu powinno spraw, aby skrypt używał pustego rozszerzenia lub listy dodatkowych właściwości.
To rozróżnienie może nie być konieczne w każdym scenariuszu. W takich przypadkach
[ -z "$var" ]
będzie dobrze.źródło
${var+x}
to poprawne zastąpienie do użycia. Użycie[ -z ${var:+x} ]
nie daje innego wyniku niż[ -z "$var" ]
.[ -z "" -a -z ${var+x} ]
Dostaje siębash: [: argument expected
do bash 4.3-ubuntu (ale nie np. Zsh). Naprawdę nie lubię odpowiedzi, używając składni, która w niektórych przypadkach działa.[ -z $var ]
nie jest bardziej „błędne” niż pominięcie cudzysłowu. Tak czy inaczej, przyjmujesz założenia dotyczące wkładu. Jeśli dobrze traktujesz pusty ciąg jako nieuzbrojony,[ -z $var ]
wystarczy.Aby sprawdzić zmienną łańcuchową o wartości innej niż zero / zero, tj. Jeśli jest ustawiona, użyj
To jest przeciwieństwo
-z
. Używam-n
więcej niż-z
.Użyłbyś tego w następujący sposób:
źródło
[[ ]]
ponad[ ]
, ponieważ[[ ]]
jest bardziej wydajny i powoduje mniej problemów w niektórych sytuacjach (zobacz to pytanie, aby wyjaśnić różnicę między nimi). Pytanie dotyczy w szczególności rozwiązania bash i nie wspomina o żadnych wymaganiach dotyczących przenośności.[]
działa lepiej zwłaszcza w przypadku skryptów powłoki (non-bash).set -u
.-n
jest to test domyślny, więc prościej[ "$1" ]
lub[[ $1 ]]
też działaj. Należy również pamiętać, że przy[[ ]]
cytowaniu nie jest konieczne .Oto jak sprawdzić, czy parametr jest nieustawiony , pusty („Null”) lub ustawiony za pomocą wartości :
Źródło: POSIX: Rozszerzenie parametrów :
Aby pokazać to w akcji:
źródło
set foo; echo ${1:-set but null or unset}
echos "foo";set --; echo ${1:-set but null or unset}
echa ustawione, ale zerowe ...set
:-): ${FOOBAR:=/etc/foobar.conf}
ustawienie domyślnej wartości zmiennej, jeśli jest ona nieustawiona lub zerowa.parameter
to dowolna nazwa zmiennej.word
to ciąg znaków, który należy zastąpić w zależności od używanej składni w tabeli i tego, czy zmienna$parameter
jest ustawiona, ustawiona, ale pusta, czy też nie. Nie komplikuje to, aleword
może również zawierać zmienne! Może to być bardzo przydatne do przekazywania opcjonalnych argumentów oddzielonych znakiem. Na przykład:${parameter:+,${parameter}}
wyświetla przecinek oddzielony,,$parameter
jeśli jest ustawiony, ale nie ma wartości null. W tym przypadkuword
jest,${parameter}
Chociaż większość podanych tu technik jest poprawna, bash 4.2 obsługuje rzeczywisty test na obecność zmiennej ( man bash ), zamiast testować wartość zmiennej.
Warto zauważyć, że to podejście nie spowoduje błędu, gdy zostanie użyte do sprawdzenia, czy zmienna nie jest ustawiona w trybie
set -u
/set -o nounset
, w przeciwieństwie do wielu innych podejść, takich jak używanie[ -z
.źródło
[[ -v aaa ]]; echo $?
==>-bash: conditional binary operator expected
-bash: syntax error near 'aaa'
declare -a foo
Można to zrobić na wiele sposobów, jednym z nich jest:
To się powiedzie, jeśli 1 $ jest zerowy lub nieustawiony
źródło
[[ ]]
jest niczym innym jak pułapką przenośności.if [ -n "$1" ]
należy go tutaj użyć.foo=""
,$foo
ma wartość, ale-z
po prostu zgłosi, że jest pusta. I-z $foo
wybuchnie, jeśli maszset -o nounset
.foo=
), To odpowiedź Russela jest poprawna.Zawsze znajduję tabelę POSIX w drugiej odpowiedzi wolną od grokowania, więc oto moje zdanie:
Zauważ, że każda grupa (z poprzedzającym dwukropkiem i bez niego) ma takie same ustawione i nieuzbrojone przypadki, więc jedyną różnicą jest sposób obsługi pustych przypadków.
W poprzednim dwukropku puste i nieuzbrojone przypadki są identyczne, więc użyłbym tych tam, gdzie to możliwe (tj. Używałbym
:=
nie tylko=
, ponieważ pusty przypadek jest niespójny).Nagłówki:
VARIABLE
nie jest pusty (VARIABLE="something"
)VARIABLE
jest puste / null (VARIABLE=""
)VARIABLE
że nie istnieje (unset VARIABLE
)Wartości:
$VARIABLE
oznacza, że wynikiem jest pierwotna wartość zmiennej."default"
oznacza, że wynikiem był podany ciąg zastępczy.""
oznacza, że wynik ma wartość NULL (pusty ciąg).exit 127
oznacza, że skrypt przestaje działać z kodem wyjścia 127.$(VARIABLE="default")
oznacza, że wynikiem jest oryginalna wartość zmiennej, a podany ciąg zastępujący jest przypisywany do zmiennej do wykorzystania w przyszłości.źródło
VARIABLE=""
można zapisać jakoVARIABLE=
. Mimo to ten pierwszy jest bardziej czytelny.Aby zobaczyć, czy zmienna nie jest pusta, używam
Odwrotny test sprawdza, czy zmienna jest rozbrojona lub pusta:
Aby sprawdzić, czy zmienna jest ustawiona (pusta czy niepusta), używam
Przeciwnie, jeśli zmienna jest rozbrojona:
źródło
[ $isMac ] && param="--enable-shared"
${variable+x}
uzyskiwaniax
iff$variable
) prawie pół roku wcześniej. Ma też znacznie więcej szczegółów wyjaśniających, dlaczego tak jest.${variable+x}
jest mniej czytelny (i oczywisty)W nowoczesnej wersji Bash (chyba 4.2 lub nowszej; nie wiem na pewno), spróbowałbym:
źródło
[ -v "$VARNAME" ]
nie jest to niepoprawne, ale po prostu wykonuje inny test. ZałóżmyVARNAME=foo
; następnie sprawdza, czy jest ustawiona zmienna o nazwiefoo
.-v
mieć przenośność, nie jest zgodny z POSIX[: -v: unexpected operator
, trzeba zapewnić, aby użyćbash
zamiastsh
.Chociaż w przypadku argumentów zwykle najlepiej jest przetestować $ #, czyli, moim zdaniem, liczbę argumentów.
źródło
[ "$1" != "" ]
(lub[ -n "$1" ]
) ...$1
zostanie ustawiony pusty ciąg.$1
jest ustawiona na pusty ciąg.set -o nounset
jest włączone.Uwaga
Daję odpowiedź bardzo skoncentrowaną na Bash z powodu
bash
tagu.Krótka odpowiedź
Tak długo, jak masz do czynienia z nazwanymi zmiennymi w Bash, ta funkcja powinna zawsze informować, czy zmienna została ustawiona, nawet jeśli jest to pusta tablica.
Dlaczego to działa
W Bash (przynajmniej do 3.0), jeśli
var
jest zmienną zadeklarowaną / ustawioną, wówczasdeclare -p var
wypisujedeclare
polecenie, które ustawi zmiennąvar
na dowolny jej aktualny typ i wartość, i zwraca kod statusu0
(sukces). Jeśli nievar
jest zadeklarowany,declare -p var
wyświetla komunikat o błędziestderr
i zwraca kod stanu1
. Użycie&>/dev/null
przekierowuje zarówno zwykłe, jakstdout
istderr
wyjściowe/dev/null
, nigdy nie widoczne i bez zmiany kodu statusu. Dlatego funkcja zwraca tylko kod statusu.Dlaczego inne metody (czasami) zawodzą w Bash
Gdy ta metoda zawiedzie w Bash
To działa tylko dla nazwanych zmiennych (włącznie
$_
) nie pewnych zmiennych specjalnych ($!
,$@
,$#
,$$
,$*
,$?
,$-
,$0
,$1
,$2
, ..., a wszelkie mogę zapomnieć). Ponieważ żadna z nich nie jest tablicami, styl POSIX[ -n "${var+x}" ]
działa dla wszystkich tych zmiennych specjalnych. Ale uważaj na zawijanie go w funkcję, ponieważ wiele specjalnych zmiennych zmienia wartości / istnienie podczas wywoływania funkcji.Uwaga dotycząca zgodności z powłoką
Jeśli twój skrypt ma tablice i próbujesz uczynić go kompatybilnym z jak największą liczbą powłok, rozważ użycie
typeset -p
zamiast niegodeclare -p
. Czytałem, że ksh obsługuje tylko te pierwsze, ale nie byłem w stanie tego przetestować. Wiem, że Bash 3.0+ i Zsh 5.5.1 obsługują obatypeset -p
ideclare -p
różnią się tylko tym, w którym jedno jest alternatywą dla drugiego. Ale nie testowałem różnic poza tymi dwoma słowami kluczowymi i nie testowałem innych powłok.Jeśli potrzebujesz, aby skrypt był zgodny z POSIX sh, nie możesz używać tablic. Bez tablic
[ -n "{$var+x}" ]
działa.Kod porównawczy dla różnych metod w Bash
Ta funkcja resetuje zmienną
var
,eval
s przekazany kod, uruchamia testy w celu ustalenia, czyvar
jest ustawiona przezeval
kod d, a na koniec wyświetla wynikowe kody stanu dla różnych testów.Ja omijając
test -v var
,[ -v var ]
i[[ -v var ]]
ponieważ dają one takie same wyniki ze standardem POSIX[ -n "${var+x}" ]
, wymagając Basha wersji 4.2 lub nowszej. Pomijam również,typeset -p
ponieważ jest taki sam, jakdeclare -p
w testowanych przeze mnie powłokach (Bash 3.0 do 5.0 i Zsh 5.5.1).Kod przypadku testowego
Zauważ, że wyniki testu mogą być nieoczekiwane z powodu traktowania przez Bash indeksów tablic nienumerycznych jako „0”, jeśli zmienna nie została zadeklarowana jako tablica asocjacyjna. Również tablice asocjacyjne działają tylko w Bash 4.0+.
Wyjście testowe
W mnemoniki badań odpowiadają w wierszu nagłówka, aby
[ -n "$var" ]
,[ -n "${var+x}" ]
,[ "${#var[@]}" != 0 ]
ideclare -p var
, odpowiednio.Podsumowanie
źródło
declare -p var &>/dev/null
) jest TYLKO tą, która działa. DZIĘKUJĘ CI!... &> /dev/null
ale SO nie pozwala mi na edycję pojedynczego znaku 🙄 (musi być> 6 znaków - nawet próbowałem dodać białe znaki ale to nie działało). Warto również zmienić funkcję, aby przełączyć się$1
na próbkę o nazwie zmienna (np.OUTPUT_DIR
), Ponieważ, jak zauważyłeś, specjalne zmienne, takie jak$1
, nie działają tutaj. W każdym razie jest to zmiana krytyczna, w przeciwnym razie kod chce utworzyć plik o nazwienull
w katalogu względnym o nazwiedev
. BTW - świetna odpowiedź!declare -p PATH &> /dev/null
zwraca 0, gdziedeclare -p ASDFASDGFASKDF &> /dev/null
zwraca 1. 1. (w wersji bash 5.0.11 (1))declare var
deklaruje zmienną var, ale nie ustawia jej pod względemset -o nounset
: Testuj za pomocądeclare foo bar=; set -o nounset; echo $bar; echo $foo
/
! Naprawiłem to, ale myślę, że logika jest wystarczająco myląca, aby uzasadnić działanie funkcji, szczególnie w świetle komentarza @ xebeche. @ xebeche To jest niewygodne dla mojej odpowiedzi… Wygląda na to, że będę musiał spróbować czegoś takiego jakdeclare -p "$1" | grep =
lubtest -v "$1"
.Dla tych, którzy chcą sprawdzić, czy nie jest ustawiony lub pusty w skrypcie z
set -u
:Regularne
[ -z "$var" ]
sprawdzanie zakończy się niepowodzeniem zvar; unbound variable
if,set -u
ale[ -z "${var-}" ]
rozwija się do pustego łańcucha, jeślivar
jest rozbrojony bez niepowodzenia.źródło
${var:-}
, nie${var-}
. Ale w Bash mogę potwierdzić, że działa nawet bez dwukropka.${var:-}
i${var-}
oznaczają różne rzeczy.${var:-}
rozwinie się do pustego ciągu, jeśli jestvar
rozbrojony lub zerowy, i${var-}
rozwinie się do pustego ciągu, tylko jeśli zostanie rozbrojony.Chcesz wyjść, jeśli jest rozbrojony
To zadziałało dla mnie. Chciałem, aby mój skrypt zakończył działanie z komunikatem o błędzie, jeśli parametr nie został ustawiony.
Zwraca to z błędem po uruchomieniu
Zaznacz tylko, bez wyjścia - puste i rozbrojone są NIEPRAWIDŁOWE
Wypróbuj tę opcję, jeśli chcesz tylko sprawdzić, czy wartość set = VALID lub unset / empty = INVALID.
Lub nawet krótkie testy ;-)
Zaznacz tylko, bez wyjścia - Tylko puste jest NIEPRAWIDŁOWE
I to jest odpowiedź na pytanie. Użyj tego, jeśli chcesz tylko sprawdzić, czy wartość set / empty = VALID lub unset = INVALID.
UWAGA, „1” w „..- 1}” jest nieznaczne, może być dowolne (np. X)
Krótkie testy
Dedykuję tę odpowiedź @ mklement0 (komentarze), która wezwała mnie do dokładnej odpowiedzi na pytanie.
Odniesienie http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02
źródło
Aby sprawdzić, czy zmienna jest ustawiona na niepustą wartość, użyj
[ -n "$x" ]
, jak wskazali już inni.Przez większość czasu dobrym pomysłem jest traktowanie zmiennej, która ma pustą wartość w ten sam sposób, jak zmiennej, która jest nieuzbrojona. Ale możesz je rozróżnić, jeśli potrzebujesz:
[ -n "${x+set}" ]
("${x+set}"
rozwija się doset
ifx
jest ustawiony i do pustego ciągu jeślix
jest nieustawiony).Aby sprawdzić, czy parametr został przekazany, przetestuj
$#
, czyli liczbę parametrów przekazanych do funkcji (lub do skryptu, gdy nie ma jej w funkcji) (patrz odpowiedź Paula ).źródło
Przeczytaj sekcję „Rozszerzanie parametrów” na
bash
stronie man. Rozszerzanie parametrów nie zapewnia ogólnego testu dla ustawianej zmiennej, ale istnieje kilka rzeczy, które można zrobić z parametrem, jeśli nie jest ustawiony.Na przykład:
ustawi wartość
first_arg
równą,$1
jeśli jest przypisany, w przeciwnym razie użyje wartości „foo”. Jeślia
absolutnie konieczne jest przyjęcie pojedynczego parametru i nie istnieje żaden dobry parametr domyślny, można wyjść z komunikatem o błędzie, gdy nie podano żadnego parametru:(Zwróć uwagę na użycie
:
jako polecenia zerowego, które po prostu rozszerza wartości jego argumentów. Nie chcemy nic robić$1
w tym przykładzie, po prostu wyjdź, jeśli nie jest ustawione)źródło
: ${var?message}
.W bash możesz używać
-v
wewnątrz[[ ]]
wbudowanego:źródło
Użycie
[[ -z "$var" ]]
jest najłatwiejszym sposobem na sprawdzenie, czy zmienna została ustawiona, czy nie, ale ta opcja-z
nie rozróżnia zmiennej nieuzbrojonej od zmiennej ustawionej na pusty ciąg:Najlepiej sprawdzić to zgodnie z rodzajem zmiennej: zmienna env, parametr lub zmienna regularna.
W przypadku zmiennej env:
W przypadku parametru (na przykład w celu sprawdzenia istnienia parametru
$5
):W przypadku zmiennej regularnej (używając funkcji pomocniczej, aby zrobić to w elegancki sposób):
Uwagi:
źródło
Powyższe odpowiedzi nie działają, gdy
set -u
włączona jest opcja Bash . Nie są też dynamiczne, np. Jak testować zmienną o nazwie „manekin” jest zdefiniowany? Spróbuj tego:Powiązane: W Bash, jak sprawdzić, czy zmienna jest zdefiniowana w trybie „-u”
źródło
eval "[ ! -z \${$1:-} ]"
do oceny pośredniej:[ ! -z ${!1:-} ];
.Możesz to zrobić:
źródło
-n
i nie negować-z
.$1
, tj[ ! -z "$1" ]
. Lub możesz pisać[[ ! -z $1 ]]
w bash / ksh / zsh.$1
zostanie ustawiony pusty ciąg.Mój preferowany sposób to:
Zasadniczo więc, jeśli zmienna jest ustawiona, staje się „zaprzeczeniem wynikowego
false
” (to, co będzietrue
= „jest ustawione”).A jeśli jest rozbrojony, stanie się „zaprzeczeniem wynikowego
true
” (jak ocenia pusty wyniktrue
) (więc zakończy się jakofalse
„= NIE ustawiony”).źródło
Lub
Lub
Lub
źródło
W powłoce możesz użyć
-z
operatora, który ma wartość True, jeśli długość łańcucha wynosi zero.Prosty jednowarstwowy do ustawienia domyślnego,
MY_VAR
jeśli nie jest ustawiony, w przeciwnym razie opcjonalnie możesz wyświetlić komunikat:źródło
źródło
$1
,$2
A nawet$N
zawsze jest ustawiony. Przepraszamy, to nie powiodło się.Znalazłem (znacznie) lepszy kod do zrobienia tego, jeśli chcesz sprawdzić coś w
$@
.Dlaczego to wszystko? Wszystko
$@
istnieje w bash, ale domyślnie jest to pusty, więctest -z
itest -n
nie mógł pomóc.Aktualizacja: Możesz również policzyć liczbę znaków w parametrach.
źródło
źródło
Tego używam na co dzień:
Działa to dobrze w systemach Linux i Solaris aż do wersji bash 3.0.
źródło
test -n "$(eval "echo "\${${1}+x}"")"
również ekwiwalentem:[[ ${!1+x} ]]
Lubię funkcje pomocnicze, aby ukryć prymitywne szczegóły bash. W takim przypadku powoduje to jeszcze więcej (ukrytego) chamstwa:
Ponieważ po raz pierwszy miałem błędy w tej implementacji (zainspirowane odpowiedziami Jensa i Lionela), wpadłem na inne rozwiązanie:
Uważam, że jest bardziej bezpośredni, bardziej wstydliwy i łatwiejszy do zrozumienia / zapamiętania. Przypadek testowy pokazuje, że jest równoważny:
Przypadek testowy także pokazuje, że
local var
ma nie deklarują var (o ile nie następuje „=”). Od dłuższego czasu myślałem, że zadeklarowałem zmienne w ten sposób, aby odkryć teraz, że po prostu wyraziłem zamiar ... Chyba nie można tego zrobić.BONUS: przypadek użycia
Najczęściej używam tego testu, aby nadać (i zwrócić) parametry funkcjom w nieco „elegancki” i bezpieczny sposób (prawie przypominający interfejs ...):
Wywołanie ze wszystkimi wymaga zadeklarowanych zmiennych
jeszcze:
źródło
Po przejrzeniu wszystkich odpowiedzi działa to również:
jeśli nie podasz
SOME_VAR
zamiast tego, co mam$SOME_VAR
, ustawi to na pustą wartość;$
jest konieczne, aby to zadziałało.źródło
set -u
efekt, który wydrukujeunboud variable
błądAby sprawdzić, czy var jest ustawiony, czy nie
źródło
$var
zostanie ustawiony pusty ciąg.Jeśli chcesz sprawdzić, czy zmienna jest powiązana lub niezwiązana, działa to dobrze, nawet po włączeniu opcji rzeczownika:
źródło
set -o nounset
, nieset -o noun set
. Działa to tylko dla edytowanych zmiennychexport
. Zmienia również ustawienia w sposób, którego cofnięcie jest niewygodne.Zawsze używam tego, ponieważ wydaje się łatwy do zrozumienia dla każdego, kto zobaczy kod po raz pierwszy:
A jeśli chcesz sprawdzić, czy nie pusty;
Otóż to.
źródło
[[ ... ]]
zamiast[ ... ]
. To ostatnie jest w rzeczywistości zewnętrznym poleceniem i nie miałoby żadnego wglądu w to, czy zmienna jest ustawiona, czy nie.