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 ?
}
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.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
.
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.
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
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
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
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.
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
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
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)
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
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 ).
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
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.
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
}
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"
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.
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."
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").
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
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' fiDlaczego 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
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
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
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.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
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ścieB
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.
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
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
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życiedeclare -p
, Jak to również pokazuje Peregring-LK'S answer , jest naprawdę przypadkowy. W przeciwnym razie oczywiście bym to przypisał!
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
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