Jeśli w skrypcie powłoki zdefiniuję zmienną taką jak FOO=25, czy istnieje różnica między odwoływaniem się do niej jako $FOO$i ${FOO}$?
Jeśli w skrypcie powłoki zdefiniuję zmienną taką jak FOO=25, czy istnieje różnica między odwoływaniem się do niej jako $FOO$i ${FOO}$?
Odpowiedzi:
W większości przypadków oba $vari ${var}są takie same. (Pamiętaj, że nie wolno używać $na końcu!)
Jednym z przykładów, w których potrzebujesz nawiasów klamrowych, jest umieszczenie zmiennej w ciągłym łańcuchu.
Przykład:
var=hel
echo ${var}lo
wyjdzie hello.
Aby odpowiedzieć na twoje główne pytanie, ${foo}nazywa się to „rozszerzaniem parametrów” . Mówiąc ściślej , $sam rozpoczyna ekspansję parametrów, { }są one właściwie opcjonalne zgodnie ze specyfikacją POSIX , ale mogą być przydatne do wskazania końca nazwy zmiennej:
$ foo="bar"
$ echo $fooBaz ## fails, no variable named $fooBaz exists
$ echo ${foo}Baz ## works, $foo is expanded and the string Baz is appended
barBaz
Zasadniczo $fooi ${foo}są identyczne. Oprócz przypadków takich jak powyższe lub podczas manipulacji ciągami są one całkowicie równoważne.
Jednak tak naprawdę nie powinieneś używać żadnego z nich. Ogólna zasada jest taka, że z nielicznymi wyjątkami należy zawsze używać "$foo"lub "${foo}"nigdy, $foolub nigdy ${foo}. Zawsze powinieneś cytować swoje zmienne, aby uniknąć wywoływania operatora split + glob (więcej na ten temat później). Na pewno nie chcesz $foo$. Finał nie $ma znaczenia:
$ foo="bar"
$ echo "$foo$"
bar$
Tak więc, chociaż zmienne nienotowane są czasem OK:
$ echo $foo
bar
Zazwyczaj nie są i tak naprawdę należy ich unikać:
$ if [ -n $foo ]; then echo empty; else echo "not empty"; fi ## fails
empty
$ if [ -n "$foo" ]; then echo empty; else echo "not empty"; fi ## works
not empty
Zauważ, że nawiasy kwadratowe również tutaj nie pomagają:
$ if [ -n ${foo} ]; then echo empty; else echo "not empty"; fi ## fails
empty
$ if [ -n "${foo}" ]; then echo empty; else echo "not empty"; fi ## works
not empty
Kiedy używasz $foolub ${foo}, powłoka podzieli wartość zapisaną w zmiennej na białe znaki (można to zmienić, ustawiając IFSzmienną na coś innego) na listę, a następnie każdy element listy jest traktowany jako wzorzec globalny i rozwijany do wszystkie pasujące pliki lub katalogi. Jest to znane jako operator split + glob . Aby to zilustrować, rozważ katalog z dwoma plikami:
$ ls -l
-rw-r--r-- 1 terdon terdon 0 Oct 9 18:16 file1
-rw-r--r-- 1 terdon terdon 0 Oct 9 18:16 file2
Teraz ustawmy zmienną na foo *:
$ foo="foo *"
Co się stanie, jeśli spróbujemy sprawdzić, czy istnieje plik o tej nazwie?
$ if [ -e $foo ]; then echo "file exists"; else echo "no such file"; fi
file exists
Zmienna została podzielona na fooi *, ponieważ ponieważ *jest to symbol wieloznaczny pasujący do dowolnego ciągu, powłoka informuje, że plik o nazwie foo *exxists. Jeśli jednak podamy to poprawnie, nie stanie się tak:
$ if [ -e "$foo" ]; then echo "file exists"; else echo "no such file"; fi
no such file
To był trywialny przykład ilustrujący tę kwestię. Wyobraź sobie, że rmzamiast tego użyłem echo.
Pierwsza zasada: zawsze podawaj swoje zmienne. Możesz użyć albo, "$foo"albo "${foo}"zacytować to tak czy inaczej. Aby uzyskać więcej informacji na temat bezpiecznego używania zmiennych, spójrz na te posty:
$ var="foo *"być $ foo="foo *"? varNigdzie nie używasz .
$w końcu! Będzie traktowany jako normalny znak, a nie jako część nazwy zmiennej.