Jestem mylony z używaniem pojedynczych lub podwójnych nawiasów. Spójrz na ten kod:
dir="/home/mazimi/VirtualBox VMs"
if [[ -d ${dir} ]]; then
echo "yep"
fi
Działa idealnie, chociaż ciąg zawiera spację. Ale kiedy zmienię go na pojedynczy nawias:
dir="/home/mazimi/VirtualBox VMs"
if [ -d ${dir} ]; then
echo "yep"
fi
To mówi:
./script.sh: line 5: [: /home/mazimi/VirtualBox: binary operator expected
Kiedy zmienię to na:
dir="/home/mazimi/VirtualBox VMs"
if [ -d "${dir}" ]; then
echo "yep"
fi
To działa dobrze. Czy ktoś może wyjaśnić, co się dzieje? Kiedy powinienem przypisywać podwójne cudzysłowy wokół zmiennych, "${var}"
aby zapobiec problemom powodowanym przez spacje?
Odpowiedzi:
Pojedynczy nawias
[
to tak naprawdę aliastest
polecenia, nie składnia.Jedną z wad (wielu) pojedynczego nawiasu jest to, że jeśli jeden lub więcej operandów próbuje ocenić zwrócenie pustego ciągu, będzie narzekał, że spodziewał się dwóch operandów (binarnych). Oto dlaczego ludzie tak robią
[ x$foo = x$blah ]
,x
gwarancje, że operand nigdy nie przekształci się w pusty ciąg.Z
[[ ]]
drugiej strony podwójny nawias ma składnię i jest znacznie bardziej wydajny[ ]
. Jak się dowiedziałeś, nie ma problemu z pojedynczym operandem, a także pozwala na większą składnię podobną do C z>, <, >=, <=, !=, ==, &&, ||
operatorami.Moje zalecenie jest następujące: Jeśli twój tłumacz jest
#!/bin/bash
, to zawsze używaj[[ ]]
Ważne jest, aby pamiętać, że
[[ ]]
nie jest obsługiwany przez wszystkie powłoki POSIX, jednak wiele powłok obsługuje takie jakzsh
iksh
opróczbash
źródło
$foo
jest!
lub(
lub-n
... Ten problem nie ma być problemem z powłokami POSIX, w których liczba argumentów (obok[
i]
) nie jest większa niż cztery.[ x$foo = x$blah ]
jest tak samo błędne jak[ $foo = $bar ]
.[ "$foo" = "$bar" ]
jest poprawny w każdej powłoce zgodnej z POSIX,[ "x$foo" = "x$bar" ]
działałby w dowolnej powłoce podobnej do Bourne'a, alex
nie dotyczy przypadków, w których masz puste łańcuchy, ale gdzie$foo
może być!
lub-n
...[
nie jest to dokładnie aliastest
. Gdyby tak było,test
zaakceptowałby zamykający nawias kwadratowy.test -n foo ]
. Aletest
nie[
wymaga i wymaga jednego.[
jest identycznytest
pod wszystkimi innymi względami, ale nie tak toalias
działa. Bash opisuje[
itest
jako wbudowane powłoki , ale[[
jako słowo kluczowe powłoki .>=
i<=
[
Komenda jest zwykłym poleceń. Chociaż większość powłok zapewnia go jako wbudowaną funkcję zwiększania wydajności, przestrzega ona normalnych reguł składniowych powłoki.[
jest dokładnie równoważnetest
, z wyjątkiem tego, że[
wymaga on]
jako ostatniego argumentu itest
nie robi tego.Podwójne nawiasy kwadratowe
[[ … ]]
mają specjalną składnię. Zostały one wprowadzone w ksh (kilka lat później[
), ponieważ[
ich używanie może być kłopotliwe i[[
pozwala na nowe fajne dodatki, które używają znaków specjalnych powłoki. Na przykład możesz pisaćponieważ całe wyrażenie warunkowe jest analizowane przez powłokę, podczas gdy
[ $x = foo && $y = bar ]
najpierw zostanie podzielone na dwie komendy[ $x = foo
i$y = bar ]
rozdzielone przez&&
operatora. Podobnie podwójne nawiasy kwadratowe umożliwiają takie rzeczy, jak składnia dopasowania wzorca, np.[[ $x == a* ]]
Sprawdzenie, czy wartośćx
zaczyna się oda
; w pojedynczych nawiasach rozwinie sięa*
to do listy plików, których nazwy zaczynają sięa
od bieżącego katalogu. Podwójne nawiasy kwadratowe zostały po raz pierwszy wprowadzone w ksh i są dostępne tylko w ksh, bash i zsh.W nawiasach pojedynczych należy używać podwójnych cudzysłowów wokół podstawień zmiennych, tak jak w większości innych miejsc, ponieważ są one tylko argumentami polecenia (którym jest to
[
polecenie). W podwójnych nawiasach kwadratowych nie potrzebujesz podwójnych cudzysłowów, ponieważ powłoka nie wykonuje dzielenia ani globowania słów: analizuje wyrażenie warunkowe, a nie polecenie.Wyjątkiem jest jednak
[[ $var1 = "$var2" ]]
sytuacja, w której potrzebujesz cudzysłowów, jeśli chcesz wykonać porównanie ciągów bajt-bajt, w przeciwnym razie$var2
byłby to wzorzec do dopasowania$var1
.Jednej rzeczy, z którą nie można zrobić,
[[ … ]]
jest użycie zmiennej jako operatora. Na przykład jest to całkowicie legalne (ale rzadko przydatne):W twoim przykładzie
komenda wewnątrz
if
jest[
z 4 argumentów-d
,/home/mazimi/VirtualBox
,VMs
i]
. Powłoka analizuje,-d /home/mazimi/VirtualBox
a następnie nie wie, co z tym zrobićVMs
. Będziesz musiał zapobiec dzieleniu słów,${dir}
aby uzyskać poprawnie sformułowane polecenie.Ogólnie rzecz biorąc, zawsze używaj podwójnych cudzysłowów wokół podstawień zmiennych i poleceń, chyba że wiesz, że chcesz wykonać dzielenie słów i globowanie wyniku. Główne miejsca, w których nie można używać podwójnych cytatów, to:
foo=$bar
(ale zauważ, że potrzebujesz podwójnych cudzysłowów wexport "foo=$bar"
lub w przypisaniach tablicowych, takich jakarray=("$a" "$b")
);case
oświadczeniucase $foo in …
:;=
lub==
operatora (chyba, że chcesz zrobić pasujące do wzorca)[[ $x = "$y" ]]
.We wszystkich tych przypadkach poprawne jest stosowanie podwójnych cudzysłowów, więc równie dobrze możesz pominąć zaawansowane reguły i używać cudzysłowów przez cały czas.
źródło
[
rzeczywiście pochodzi z Systemu III w 1981 roku , myślałem, że jest starszy.Domniemane w tym pytaniu jest
${variable_name}
nie znaczy, co myślisz…... jeśli myślisz, że to ma coś wspólnego z problemami spowodowanymi przez przestrzenie (w wartościach zmiennych). jest do tego dobry:
${variable_name}
i nic więcej! 1 nie przynosi żadnego pożytku, chyba że natychmiast podążysz za nim ze znakiem, który może być częścią nazwy zmiennej: literą (-lub-), podkreśleniem () lub cyfrą (-). I nawet wtedy możesz obejść to:
${variable_name}
A
Z
a
z
_
0
9
Nie próbuję zniechęcać do jego używania -
echo "${bar}d"
jest to prawdopodobnie najlepsze rozwiązanie tutaj - ale zniechęcam ludzi do polegania na nawiasach klamrowych zamiast cytatów lub instynktownego stosowania nawiasów klamrowych, a następnie pytania: „Czy ja też potrzebuję cytatów ? „ Powinieneś zawsze używać cytatów, chyba że masz dobry powód, aby tego nie robić, a na pewno wiesz, co robisz._________________
1 z wyjątkiem, oczywiście, na tym, że hodowcy formy ekspansji parametru , na przykład, i bazować na składnią. Musisz także użyć , itp., Aby odnieść się do 10, 11, itd. Parametrów pozycyjnych - cytaty ci w tym nie pomogą.
${parameter:-[word]}
${parameter%[word]}
${parameter}
${10}
${11}
źródło
Do obsługi spacji i pustych | znaków specjalnych w zmiennych należy zawsze otaczać je podwójnymi cudzysłowami. Dobrym zwyczajem jest również ustawienie właściwego IFS.
Zalecane: http://www.dwheeler.com/essays/filenames-in-shell.html
źródło