Różnica między pojedynczym i podwójnym nawiasem kwadratowym w Bash
Czytam przykłady Basha o if
, ale niektóre przykłady są pisane pojedynczymi nawiasami kwadratowymi:
if [ -f $param ]
then
#...
fi
Inne z podwójnymi nawiasami kwadratowymi:
if [[ $? -ne 0 ]]
then
start looking for errors in yourlog
fi
Jaka jest różnica?
6 answers
Single []
są testami stanu zgodnymi ze standardem posix shell.
Double [[]]
są rozszerzeniem standardu []
i są obsługiwane przez bash i inne powłoki (np. zsh, ksh). Obsługują dodatkowe operacje (jak również standardowe operacje posix). Na przykład: ||
zamiast -o
i regex pasujący do =~
. Pełniejszą listę różnic można znaleźć w sekcji podręcznika bash dotyczącej konstrukcji warunkowych .
Użyj []
kiedy chcesz, aby twój skrypt był przenośne w poprzek muszli. Użyj [[]]
, jeśli chcesz, aby wyrażenia warunkowe nie były obsługiwane przez []
i nie muszą być przenośne.
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-11-24 16:06:32
Różnice w zachowaniu
Testowane w Bash 4.3.11:
-
Rozszerzenie POSIX vs Bash:
-
[
is POSIX -
[[
jest rozszerzeniem Bash1 udokumentowanym pod adresem: https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructs
-
-
Zwykłe polecenie vs Magia
-
[
to zwykła Komenda o dziwnej nazwie.]
jest po prostu ostatni argument[
.
Ubuntu 16.04 faktycznie ma plik wykonywalny w
/usr/bin/[
dostarczony przez coreutils, ale wbudowana wersja bash ma pierwszeństwo.Nic nie jest zmieniane w sposób, w jaki Bash przetwarza polecenie.
W szczególności,
<
jest przekierowaniem,&&
i||
łączy wiele poleceń,( )
generuje podshell, o ile nie jest unikalny przez\
, a rozszerzenie Worda odbywa się jak zwykle.-
[[ X ]]
jest pojedynczą konstrukcją, która sprawia, żeX
jest analizowany magicznie.<
,&&
,||
i()
są traktowane specjalnie, a zasady dzielenia wyrazów są różne.Istnieją również dalsze różnice, takie jak
=
i=~
.
W języku Bashese:
[
jest wbudowanym poleceniem, a {[1] } jest słowem kluczowym: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword -
-
<
-
[[ a < b ]]
: leksykografia porównanie -
[ a \< b ]
: to samo co wyżej.\
wymagane lub robi przekierowanie jak dla każdego innego polecenia. Rozszerzenie Bash. -
expr a \< b > /dev/null
: equivalent POSIX2, zobacz: Jak testować ciągi znaków leksykograficznych mniejszych lub równych w Bash?
-
-
&&
i||
-
[[ a = a && b = b ]]
: true, logiczne i -
[ a = a && b = b ]
: błąd składni,&&
parsed as an and command separatorcmd1 && cmd2
-
[ a = a -a b = b ]
: odpowiednik, ale deprecated by POSIX3 -
[ a = a ] && [ b = b ]
: POSIX i niezawodny odpowiednik
-
-
(
-
[[ (a = a || a = b) && a = b ]]
: false -
[ ( a = a ) ]
: błąd składni,()
jest interpretowany jako subshell -
[ \( a = a -o a = b \) -a a = b ]
: odpowiednik, ale()
jest przestarzały przez POSIX -
{ [ a = a ] || [ a = b ]; } && [ a = b ]
odpowiednik POSIX 5
-
-
Dzielenie wyrazów i generowanie nazw plików po rozszerzeniach (split+glob)
-
x='a b'; [[ $x = 'a b' ]]
: true, quotes not needed -
x='a b'; [ $x = 'a b' ]
: błąd składni, rozszerza się do[ a b = 'a b' ]
-
x='*'; [ $x = 'a b' ]
: błąd składni, jeśli w bieżącym katalogu znajduje się więcej niż jeden plik. -
x='a b'; [ "$x" = 'a b' ]
: odpowiednik POSIX
-
-
=
-
[[ ab = a? ]]
: true, bo to robi dopasowanie wzorca (* ? [
są magiczne). Nie powoduje rozszerzenia glob do plików w bieżącym katalogu. -
[ ab = a? ]
:a?
Globus rozszerza się. Więc może być prawda lub FAŁSZ w zależności od plików w bieżący katalog. -
[ ab = a\? ]
: false, not glob -
=
i==
są takie same w[
i[[
, ale==
jest rozszerzeniem Bash. -
case ab in (a?) echo match; esac
: odpowiednik POSIX -
[[ ab =~ 'ab?' ]]
: false4, traci magię z''
-
[[ ab? =~ 'ab?' ]]
: true
-
-
=~
-
[[ ab =~ ab? ]]
: true, POSIX extended regular expression match,?
does not glob expand -
[ a =~ a ]
: błąd składni. Brak odpowiednika bash. -
printf 'ab\n' | grep -Eq 'ab?'
: odpowiednik POSIX (tylko dane jednoliniowe) -
awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?'
: odpowiednik POSIX.
-
Zalecenie : Zawsze używaj []
.
Istnieją odpowiedniki POSIX dla każdej [[ ]]
konstrukcji, którą widziałem.
Jeśli używasz [[ ]]
ty:
- utrata przenośności
- zmusić czytelnika do poznania zawiłości innego rozszerzenia bash.
[
to zwykłe polecenie z dziwna nazwa, brak specjalnej semantyki.
1 w 1998 roku, w wyniku połączenia dwóch poprzednich części, powstała nowa wersja gry.]}
2 ale nie dla niektórych wartości 3 a także nie dla niektórych wartości 4 w bash 3.2 i nowszych i pod warunkiem, że kompatybilność z bash 3.1 nie jest włączona (jak z 5 chociaż grupowanie (tutaj z a
lub b
(jak +
lub index
) i porównuje numeryczne, jeśli a
i b
wyglądają jak liczby dziesiętne. Działa na obie strony.a
lub b
jak !
lub (
.BASH_COMPAT=3.1
){...;}
Grupa poleceń zamiast (...)
, która uruchamiałaby niepotrzebny subshell) nie jest konieczne jako operatory powłoki ||
i &&
(w przeciwieństwie do ||
i &&
[[...]]
operatorzy lub -o
/-a
[
operatory) mają jednakowy pierwszeństwo. Więc [ a = a ] || [ a = b ] && [ a = b ]
byłoby równoważne.
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
2021-01-06 09:00:47
Wewnątrz pojedynczych nawiasów do badania stanu (tj. [ ... ]), niektóre operatory, takie jak single =
, są obsługiwane przez wszystkie powłoki, podczas gdy użycie operatora ==
nie jest obsługiwane przez niektóre starsze powłoki.
Wewnątrz podwójnych nawiasów do testu warunków (tj. [[ ... ]]), nie ma różnicy pomiędzy używaniem =
lub ==
w starych lub nowych powłokach.
Edit: powinienem również zauważyć, że: w bash Zawsze używaj podwójnych nawiasów [[... ]] jeśli to możliwe, ponieważ jest to bezpieczniejsze niż pojedyncze wsporniki. Ja zilustruj dlaczego za pomocą następującego przykładu:
if [ $var == "hello" ]; then
Jeśli $ var jest null / empty, to skrypt widzi to:
if [ == "hello" ]; then
Który złamie twój skrypt. Rozwiązaniem jest użycie podwójnych nawiasów lub Zawsze pamiętaj o umieszczaniu cudzysłowów wokół zmiennych ("$var"
). Podwójne nawiasy to lepsza praktyka kodowania defensywnego.
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-11-24 15:59:11
[[
jest słowem kluczowym bash podobnym do (ale potężniejszym niż) polecenia [
.
Zobacz
Http://mywiki.wooledge.org/BashFAQ/031 i http://mywiki.wooledge.org/BashGuide/TestsAndConditionals
Jeśli nie piszesz dla POSIX sh, zalecamy [[
.
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-04-25 04:07:24
Możesz użyć podwójnych nawiasów kwadratowych do dopasowania regex, np.:
if [[ $1 =~ "foo.*bar" ]] ; then
(o ile wersja Basha, której używasz, obsługuje tę składnię)
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-11-24 15:58:48
Instrukcja Bash mówi:
W przypadku użycia z [[, operatory " " sortują leksykograficznie używając bieżącego ustawienia lokalnego. Polecenie test używa ASCII zamawiam.
(polecenie test jest identyczne 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
2015-10-28 23:43:40