Jak sprawdzić, czy zmienna jest ustawiona w Bash?

Skąd mam wiedzieć, czy zmienna jest ustawiona w Bash?

Na przykład, jak sprawdzić, czy użytkownik podał pierwszy parametr funkcji?

function a {
    # if $1 is set ?
}
Author: nbro, 2010-08-30

30 answers

(Zwykle) właściwa droga

if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi

Gdzie ${var+x} jest rozszerzeniem parametru , który ocenia do zera, jeśli var jest unset i zastępuje łańcuch x w przeciwnym razie.

Cytaty Dygresja

Cudzysłowy mogą być pominięte (więc możemy powiedzieć ${var+x} zamiast "${var+x}"), ponieważ ta składnia i użycie gwarantuje, że będzie to rozszerzać się tylko do czegoś, co nie wymaga cudzysłowów (ponieważ albo rozszerza się do x (który nie zawiera łamów słów, więc nie potrzebuje cudzysłowów), albo do czegoś, co nie wymaga cudzysłowów. nothing (co skutkuje [ -z ], co wygodnie ocenia do tej samej wartości (true), co [ -z "" ])).

Jednak, podczas gdy cytaty można bezpiecznie pominąć, i nie było to od razu oczywiste dla wszystkich (nie było to nawet oczywiste dla pierwszego autora tego wyjaśnienia cytatów , który jest również głównym koderem Bash), czasami lepiej byłoby napisać rozwiązanie z cudzysłowami jako [ -z "${var+x}" ], przy bardzo małym możliwym koszcie kary za prędkość o(1). Pierwszy autor dodał również to jako komentarz obok kodu używającego tego rozwiązania podając adres URL do tej odpowiedzi, który teraz zawiera również wyjaśnienie, dlaczego cytaty mogą być bezpiecznie pominięte.

(często) w złą stronę

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 wyłączona, i zmiennej, która jest ustawiona na pusty łańcuch. To znaczy, jeśli var='', to powyższe rozwiązanie wyświetli "var jest puste".

Rozróżnienie między unset I " set to the empty string " jest niezbędny w sytuacjach, gdy użytkownik musi podać rozszerzenie lub dodatkową listę właściwości, a nie podanie ich domyślnie oznacza niepustą wartość, podczas gdy podanie pustego ciągu powinno sprawić, że skrypt użyje pustego rozszerzenia lub listy dodatkowych właściwości.

Rozróżnienie może jednak nie być istotne w każdym scenariuszu. W takich przypadkach {[12] } będzie dobrze.

 1678
Author: Lionel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-15 18:39:20

Aby sprawdzić, czy zmienna łańcuchowa nie jest null/niezerowa, tzn. jeśli jest ustawiona, użyj

if [ -n "$1" ]

Jest przeciwieństwem -z. Używam -n więcej niż -z.

 676
Author: mbrannig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-13 15:42:36

Oto jak sprawdzić, czy parametr jest unset, lub empty ("Null") lub ustawiony z wartością :

+--------------------+----------------------+-----------------+-----------------+
|                    |       parameter      |     parameter   |    parameter    |
|                    |   Set and Not Null   |   Set But Null  |      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 |
+--------------------+----------------------+-----------------+-----------------+

Source: POSIX: Parameter Expansion :

We wszystkich przypadkach pokazanych za pomocą "substitute", wyrażenie jest zastępowane pokazaną wartością. We wszystkich przypadkach pokazanych z "assign" parametr jest przypisany tej wartości, która również zastępuje wyrażenie.

 400
Author: Jens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-11 17:19:35

Istnieje wiele sposobów, aby to zrobić, z następujących jest jednym z nich:

if [ -z "$1" ]

To się powiedzie, jeśli $1 jest null lub unset

 168
Author: ennuikiller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-07 22:55:45

Podczas gdy większość podanych tu technik jest poprawna, bash 4.2 obsługuje rzeczywisty test na obecność zmiennej (man bash ), zamiast testowania wartości zmiennej.

[[ -v foo ]]; echo $?
# 1

foo=bar
[[ -v foo ]]; echo $?
# 0

foo=""
[[ -v foo ]]; echo $?
# 0
 154
Author: Russell Harmon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-11 19:46:43

Aby sprawdzić, czy zmienna jest nonempty, używam

if [[ $var ]]; then ...       # `$var' expands to a nonempty string

Przeciwny test sprawdza, czy zmienna jest wyłączona lub pusta:

if [[ ! $var ]]; then ...     # `$var' expands to the empty string (set or not)

Aby sprawdzić czy zmienna jest ustawiona (pusta czy nie), używam

if [[ ${var+x} ]]; then ...   # `var' exists (empty or nonempty)
if [[ ${1+x} ]]; then ...     # Parameter 1 exists (empty or nonempty)

Odwrotne testy, jeśli zmienna nie jest ustawiona:

if [[ ! ${var+x} ]]; then ... # `var' is not set at all
if [[ ! ${1+x} ]]; then ...   # We were called with no arguments
 57
Author: phkoester,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-08 08:32:46

Zawsze znajduję tabelę POSIX w inna odpowiedź powoli do grok, więc oto moje zdanie na ten temat:

   +----------------------+------------+-----------------------+-----------------------+
   |   if VARIABLE is:    |    set     |         empty         |        unset          |
   +----------------------+------------+-----------------------+-----------------------+
 - |  ${VARIABLE-default} | $VARIABLE  |          ""           |       "default"       |
 = |  ${VARIABLE=default} | $VARIABLE  |          ""           | $(VARIABLE="default") |
 ? |  ${VARIABLE?default} | $VARIABLE  |          ""           |       exit 127        |
 + |  ${VARIABLE+default} | "default"  |       "default"       |          ""           |
   +----------------------+------------+-----------------------+-----------------------+
:- | ${VARIABLE:-default} | $VARIABLE  |       "default"       |       "default"       |
:= | ${VARIABLE:=default} | $VARIABLE  | $(VARIABLE="default") | $(VARIABLE="default") |
:? | ${VARIABLE:?default} | $VARIABLE  |       exit 127        |       exit 127        |
:+ | ${VARIABLE:+default} | "default"  |          ""           |          ""           |
   +----------------------+------------+-----------------------+-----------------------+

Zauważ, że każda grupa (z i bez poprzedzającego dwukropka) ma te same set i unset przypadki, więc jedyną różnicą jest to, jak obsługiwane są empty przypadki.

Z poprzedzającym dwukropkiem, empty i unset przypadki są identyczne, więc użyłbym tych, gdzie to możliwe (tj. użyj :=, a nie tylko =, bo pusta sprawa jest niespójna).

Nagłówki:

  • zbiór oznacza VARIABLE jest niepustym (VARIABLE="something")
  • empty oznacza VARIABLE jest puste / null (VARIABLE="")
  • unset oznacza VARIABLE nie istnieje (unset VARIABLE)

Wartości:

  • $VARIABLE oznacza, że wynikiem jest pierwotna wartość zmiennej.
  • "default" oznacza, że wynik był dostarczonym ciągiem zastępczym.
  • "" oznacza wynikiem jest null (pusty łańcuch).
  • exit 127 oznacza, że skrypt przestaje działać z kodem wyjścia 127.
  • $(VARIABLE="default") oznacza, że wynikiem jest pierwotna wartość zmiennej i dostarczony łańcuch zastępczy jest przypisany do zmiennej w celu wykorzystania w przyszłości.
 37
Author: deizel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-24 16:48:20

Na nowoczesnej wersji Basha (4.2 lub nowszej chyba; Nie wiem na pewno), spróbowałbym tego:

if [ ! -v SOMEVARIABLE ] #note the lack of a $ sigil
then
    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
 31
Author: Seamus Connor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-10 16:02:25
if [ "$1" != "" ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi

Chociaż dla argumentów zwykle najlepiej jest przetestować $#, czyli liczbę argumentów, moim zdaniem.

if [ $# -gt 0 ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi
 18
Author: Paul Creasey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-30 16:43:46

Przeczytaj sekcję "rozszerzenie parametrów" strony podręcznika bash. Rozszerzenie parametrów nie zapewnia ogólnego testu ustawianej zmiennej, ale istnieje kilka rzeczy, które możesz zrobić z parametrem, jeśli nie jest ustawiony.

Na przykład:

function a {
    first_arg=${1-foo}
    # rest of the function
}

Ustawia first_arg równą $1 jeśli jest przypisany, w przeciwnym razie używa wartości "foo". Jeśli a absolutnie musi przyjmować pojedynczy parametr, a nie istnieje żadna dobra wartość domyślna, możesz zakończyć z Komunikatem o błędzie, gdy żaden parametr nie jest podane:

function a {
    : ${1?a must take a single argument}
    # rest of the function
}

(zwróć uwagę na użycie : jako polecenia null, które rozszerza wartości swoich argumentów. Nie chcemy robić nic z $1 w tym przykładzie, po prostu wyjdź, jeśli nie jest ustawione)

 14
Author: chepner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-31 22:05:06

Chcesz wyjść, jeśli jest wyłączony

To mi pomogło. Chciałem, aby mój skrypt zakończył się z Komunikatem o błędzie, jeśli parametr nie został ustawiony.
#!/usr/bin/env bash

set -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}"

To powraca z błędem podczas uruchamiania

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, no exit - Empty i Unset są niepoprawne

Wypróbuj tę opcję, jeśli chcesz tylko sprawdzić, czy wartość set=VALID lub unset/empty=INVALID.

TSET="good val"
TEMPTY=""
unset TUNSET

if [ "${TSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID
if [ "${TUNSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID

Albo nawet krótkie testy; -)

[ "${TSET:-}"   ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY:-}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET:-}" ] && echo "VALID" || echo "INVALID"

Zaznacz tylko, brak wyjścia-tylko puste jest niepoprawne

I to jest odpowiedzią na pytanie. Użyj tego, jeśli chcesz tylko sprawdzić, czy wartość set / empty=VALID lub unset = INVALID.

Uwaga, " 1 "w"..-1}" jest nieistotne, może to być wszystko (jak x)

TSET="good val"
TEMPTY=""
unset TUNSET

if [ "${TSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TUNSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID

Krótkie testy

[ "${TSET+1}"   ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY+1}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET+1}" ] && echo "VALID" || echo "INVALID"

Tę odpowiedź Dedykuję @mklement0 (komentarze), który wyzwał mnie do odpowiedzi na pytanie dokładnie.

Odniesienie http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02

 14
Author: Jarrod Chesney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-16 04:46:12

Aby sprawdzić, czy zmienna jest ustawiona z niepustą wartością, użyj [ -n "$x" ], jak już wskazywały inne.

Przez większość czasu dobrze jest traktować zmienną, która ma pustą wartość w taki sam sposób, jak zmienną, która nie jest ustawiona. Ale można je rozróżnić, jeśli trzeba: [ -n "${x+set}" ] ("${x+set}" rozszerza do set Jeśli x jest ustawione i do pustego łańcucha Jeśli {[4] } jest nie ustawione).

Aby sprawdzić, czy parametr został przekazany, test $#, który jest liczbą parametrów przekazanych do funkcja (lub do skryptu, gdy nie jest w funkcji) (zobacz odpowiedź Pawła ).

 12
Author: Gilles,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:53

W bash możesz użyć -v wewnątrz [[ ]] wbudowanego:

#! /bin/bash -u

if [[ ! -v SOMEVAR ]]; then
    SOMEVAR='hello'
fi

echo $SOMEVAR
 10
Author: AlejandroVD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-28 21:13:34

Dla tych, którzy chcą sprawdzić unset lub empty gdy w skrypcie z set -u:

if [ -z "${var-}" ]; then
   echo "Must provide var environment variable. Exiting...."
   exit 1
fi

Zwykłe [ -z "$var" ] Sprawdzenie nie powiedzie się var; unbound variable Jeśli set -u ale [ -z "${var-}" ] rozszerza na pusty łańcuch, Jeśli {[6] } jest wyłączony bez błędu.

 9
Author: ecerulm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-16 11:26:13

Możesz zrobić:

function a {
        if [ ! -z "$1" ]; then
                echo '$1 is set'
        fi
}
 4
Author: codaddict,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-31 07:23:26

Powyższe odpowiedzi nie działają, gdy włączona jest opcja Bash set -u. Również nie są dynamiczne, np. jak sprawdzić czy zdefiniowana jest zmienna o nazwie "atrapa"? Spróbuj tego:

is_var_defined()
{
    if [ $# -ne 1 ]
    then
        echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
        exit 1
    fi
    # 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.
}

Related: W Bash, jak sprawdzić, czy zmienna jest zdefiniowana w trybie "-u"

 4
Author: kevinarpe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:27

Użycie [[ -z "$var" ]] jest najprostszym sposobem, aby dowiedzieć się, czy zmienna została ustawiona, ale ta opcja -z nie odróżnia zmiennej nie ustawionej od zmiennej ustawionej na pusty łańcuch:

$ set=''
$ [[ -z "$set" ]] && echo "Set" || echo "Unset" 
Unset
$ [[ -z "$unset" ]] && echo "Set" || echo "Unset"
Unset

Najlepiej sprawdzić ją według typu zmiennej: zmienna env, parametr lub zmienna regularna.

Dla zmiennej env:

[[ $(env | grep "varname=" | wc -l) -eq 1 ]] && echo "Set" || echo "Unset"

Dla parametru (na przykład, aby sprawdzić istnienie parametru $5):

[[ $# -ge 5 ]] && echo "Set" || echo "Unset"

Dla zmiennej regularnej (za pomocą pomocniczych funkcja, aby zrobić to w elegancki sposób):

function declare_var {
   declare -p "$1" &> /dev/null
   return $?
}
declare_var "var_name" && echo "Set" || echo "Unset"

Uwagi:

  • $#: podaje liczbę parametrów pozycyjnych.
  • declare -p: daje definicję zmiennej przekazanej jako parametr. Jeśli istnieje, zwraca 0, jeśli nie, zwraca 1 i wypisuje komunikat o błędzie.
  • $?: wyświetla kod stanu ostatniego wykonanego polecenia.
 2
Author: Peregring-lk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-10 08:10:51

W powłoce można użyć operatora -z, który jest prawdziwy, jeśli długość łańcucha wynosi zero.

Prosty jednowiersz do ustawienia domyślnego MY_VAR jeśli nie jest ustawiony, opcjonalnie możesz wyświetlić wiadomość:

[[ -z "$MY_VAR" ]] && MY_VAR="default"
[[ -z "$MY_VAR" ]] && MY_VAR="default" || echo "Variable already set."
 1
Author: kenorb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-10 16:04:12

Mój preferowany sposób jest taki:

$var=10
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$unset var
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set

Więc w zasadzie, jeśli zmienna jest ustawiona, staje się " negacją wyniku false "(co będzie true = "jest ustawione").

I, jeśli nie jest ustawiona, stanie się" negacją wynikowego true "(tak jak pusty wynik ocenia się na true) (więc zakończy się jako false = "nie ustawiony").

 1
Author: Aquarius Power,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-10 16:05:00
if [[ ${1:+isset} ]]
then echo "It was set and not null." >&2
else echo "It was not set or it was null." >&2
fi

if [[ ${1+isset} ]]
then echo "It was set but might be null." >&2
else echo "It was was not set." >&2
fi
 0
Author: solidsnack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-30 05:22:39

Znalazłem (o wiele) lepszy kod, aby to zrobić, jeśli chcesz sprawdzić cokolwiek w $@.

if [[ $1 = "" ]]
then
  echo '$1 is blank'
else
  echo '$1 is filled up'
fi
Dlaczego to wszystko? Wszystko w $@ istnieje w Bash, ale domyślnie jest puste, więc test -z i test -n nie mogą Ci pomóc.

Update: można również policzyć liczbę znaków w parametrze.

if [ ${#1} = 0 ]
then
  echo '$1 is blank'
else
  echo '$1 is filled up'
fi
 0
Author: Zlatan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-27 16:30:37
[[ $foo ]]

Lub

(( ${#foo} ))

Lub

let ${#foo}

Lub

declare -p foo
 0
Author: Steven Penny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-11 05:43:17
if [[ ${!xx[@]} ]] ; then echo xx is defined; fi
 0
Author: Graham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-12 18:43:56

Zawsze używam tego, bazując na tym, że wydaje się to łatwe do zrozumienia dla każdego, kto widzi kod po raz pierwszy: {]}

if [ "$variable" = "" ]
    then
    echo "Variable X is empty"
fi

I, jeśli chcesz sprawdzić, czy nie jest pusty;

if [ ! "$variable" = "" ]
    then
    echo "Variable X is not empty"
fi
To wszystko.
 0
Author: mijnnaam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-10 16:03:35

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}"")"
}

To działa dobrze pod Linuksem i Solarisem aż do bash 3.0.

bash-3.00$ myvar="TEST"
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ mavar=""
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ unset myvar
bash-3.00$ is_set myvar ; echo $?
1
 0
Author: fr00tyl00p,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-10 16:06:00

Jeśli var może być tablicą, to podstawienie parametru [ -z "${var+x}" ] jest niepoprawne. Aby być naprawdę pewnym w Bash musisz użyć składni tablicy Jak [ "${#var[@]}" = 0 ], Jak pokazano poniżej.

is-var-set () {
    results="\${var+x}=${var+x}\t\${#var[@]}=${#var[@]}"
    if [ -z "${var+x}" ] && [ "${#var[@]}" = 0 ]; then
        echo -e "$1: var's unset.\t$results"
    elif [ -n "${var+x}" ] && [ "${#var[@]}" != 0 ]; then
        echo -e "$1: var is set. \t$results"
    else
        echo -e "$1: Is var set? \t$results"
    fi
    unset var # so we don't have to do it everywhere else
}
W prawie wszystkich przypadkach zgadzają się. Jedyną sytuacją, w której metoda array jest dokładniejsza, jest sytuacja, w której zmienna jest niepustą tablicą z pozycją 0 unset (np. w testach 7 i A poniżej). To nieporozumienie wynika z tego, że $var jest skrótem od ${var[0]}, więc {[4] }nie sprawdza cała tablica. Oto moje testy.
unset var;      is-var-set 1 # var unset
var='';         is-var-set 2 # var[0] set to ''
var=foo;        is-var-set 3 # var[0] set to 'foo'
var=();         is-var-set 4 # var unset (all indices)
var=(foo);      is-var-set 5 # var[0] set to 'foo'
var=([0]=foo);  is-var-set 6 # var[0] set to 'foo'
var=([1]=foo);  is-var-set 7 # var[0] unset, but var[1] set to 'foo'
declare -a var; is-var-set 8 # var empty, but declared as an array
declare -A var; is-var-set 9 # var empty, but declared as an associative array
declare -A var  # Because is-var-set() conveniently unsets it
var=([xz]=foo); is-var-set A # var[xz] set to 'foo', but var's otherwise empty
declare -a var  # Demonstrate that Bash knows about var, even when there's
declare -A var; is-var-set B # apparently no way to just _check_ its existence

Oto wyjście.

1: var's unset. ${var+x}=       ${#var[@]}=0
2: var is set.  ${var+x}=x      ${#var[@]}=1
3: var is set.  ${var+x}=x      ${#var[@]}=1
4: var's unset. ${var+x}=       ${#var[@]}=0
5: var is set.  ${var+x}=x      ${#var[@]}=1
6: var is set.  ${var+x}=x      ${#var[@]}=1
7: Is var set?  ${var+x}=       ${#var[@]}=1
8: var's unset. ${var+x}=       ${#var[@]}=0
9: var's unset. ${var+x}=       ${#var[@]}=0
A: Is var set?  ${var+x}=       ${#var[@]}=1
./foo.sh: line 26: declare: var: cannot convert indexed to associative array
B: var's unset. ${var+x}=       ${#var[@]}=0

W sumie:

  • Składnia rozszerzenia parametru ${var+x} działa tak samo dobrze jak składnia tablicy ${#var[@]} w większości przypadków, np. sprawdzanie parametrów funkcji. Jedynym sposobem, aby ten przypadek mógł się złamać, jest dodanie w przyszłej wersji Bash sposobu przekazywania tablic funkcjom bez konwersji zawartości na poszczególne argumenty.
  • składnia tablicy jest wymagana dla niepustych tablic (asocjacyjny lub nie) z elementem 0 unset.
  • Żadna składnia nie wyjaśnia, co się dzieje, jeśli declare -a var została użyta bez przypisania nawet wartości null gdzieś w tablicy. Bash nadal gdzieś rozróżnia przypadek (jak widać w teście B powyżej), więc ta odpowiedź nie jest niezawodna. Na szczęście Bash konwertuje wyeksportowane zmienne środowiskowe na ciągi znaków podczas uruchamiania programu/skryptu, więc wszelkie problemy z zadeklarowanymi, ale nie ustawionymi zmiennymi będą zawarte w jednym skrypcie, przynajmniej jeśli nie pozyskiwanie innych skryptów.
 0
Author: Mark Haferkamp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-15 14:32:17

Jeśli chcesz sprawdzić, czy zmienna jest związana lub niezwiązana, działa to dobrze, nawet po włączeniu opcji nounset:

set -o noun set

if printenv variableName >/dev/null; then
    # variable is bound to a value
else
    # variable is unbound
fi
 -1
Author: user1857592,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-25 20:08:04

Lubię funkcje pomocnicze, które ukrywają surowe szczegóły Basha. W tym przypadku dodaje to jeszcze więcej (ukrytego) okrucieństwa:

# The first ! negates the result (can't use -n to achieve this)
# the second ! expands the content of varname (can't do ${$varname})
function IsDeclared_Tricky
{
  local varname="$1"
  ! [ -z ${!varname+x} ]
}

Ponieważ po raz pierwszy miałem błędy w tej implementacji (zainspirowany odpowiedziami Jensa i Lionela), wymyśliłem inne rozwiązanie:

# Ask for the properties of the variable - fails if not declared
function IsDeclared()
{
  declare -p $1 &>/dev/null
}

Uważam, że jest to bardziej proste, bardziej nieśmiałe i łatwiejsze 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 pokazuje również, że local var nie deklaruje var (chyba że po'='). Przez jakiś czas myślałem, że deklaruję zmienne w ten sposób, tylko po to, aby odkryć teraz, że tylko wyraziłem swoją intencję... To chyba nie działa.

IsDeclared_Tricky xyz: 1
IsDeclared_Tricky foo: 1
Isdeclared_tricky bar: 0
IsDeclared_Tricky baz: 0
IsDeclared xyz: 1
IsDeclared foo: 1
IsDeclared bar: 0
IsDeclared baz: 0

BONUS: usecase

Używam głównie tego test, aby nadać (i zwrócić) parametry funkcjom w sposób nieco "elegancki" i bezpieczny (niemal przypominający interfejs...):

#auxiliary functions
function die()
{
  echo "Error: $1"; exit 1
}

function assertVariableDeclared()
{
  IsDeclared "$1" || die "variable not declared: $1"
}

function expectVariables()
{
  while (( $# > 0 )); do
    assertVariableDeclared $1; shift
  done
}

# actual example
function exampleFunction()
{
  expectVariables inputStr outputStr
  outputStr="$inputStr world!"
}

function bonus()
{
  local inputStr='Hello'
  local outputStr= # remove this to trigger error
  exampleFunction
  echo $outputStr
}

bonus

Jeśli wywołane z zadeklarowanymi wszystkimi wymaganymi zmiennymi:

Hello world!

Else:

Błąd: zmienna nie Zadeklarowana: outputStr

 -1
Author: Daniel S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-01 13:23:29

Funkcje sprawdzające czy zmienna jest zadeklarowana / wyłączona

Łącznie z pustym $array=()


Następujące funkcje testują, czy dana nazwa istnieje jako zmienna

# The first parameter needs to be the name of the variable to be checked.
# (See example below)

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;} 
}
  • najpierw sprawdzając, czy zmienna jest (un)ustawiona, można uniknąć wywołania declare, jeśli nie jest to konieczne.
  • Jeśli jednak $1 zawiera nazwę pustego $array=(), wywołanie declare upewni się, że otrzymamy właściwy wynik
  • nie ma zbyt wielu danych przekazywanych do /dev / null, tak jak declare jest wywołane tylko wtedy, gdy zmienna jest wyłączona lub pusta tablica.

Funkcje te sprawdzałyby się w następujących warunkach:

a;       # is not declared
a=;      # is declared
a="foo"; # is declared
a=();    # is declared
a=("");  # is declared
unset a; # is not declared

a;       # is unset
a=;      # is not unset
a="foo"; # is not unset
a=();    # is not unset
a=("");  # is not unset
unset a; # is unset

.

Po Więcej Szczegółów

I skrypt testowy zobacz moją odpowiedź na pytanie "Jak sprawdzić, czy zmienna istnieje w bash?".

Uwaga: podobne użycie declare -p, Jak to również pokazuje Peregring-LK'S answer , jest naprawdę przypadkowy. W przeciwnym razie oczywiście bym to przypisał!

 -1
Author: Martin Rüegg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:03
case "$1" in
 "") echo "blank";;
 *) echo "set"
esac
 -2
Author: ghostdog74,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-30 15:32:16