Umiem pisać
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
wynik końcowy wydaje mi się taki sam. Dlaczego mam pisać jedno lub drugie? czy któreś z nich nie jest przenośne / POSIX?
źródło
Umiem pisać
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
wynik końcowy wydaje mi się taki sam. Dlaczego mam pisać jedno lub drugie? czy któreś z nich nie jest przenośne / POSIX?
VAR=$VAR1
jest uproszczoną wersją VAR=${VAR1}
. Są rzeczy, które może zrobić drugi, czego pierwszy nie może, na przykład odwołać się do indeksu tablicy (nieprzenośny) lub usunąć podciąg (POSIX-przenośny). Zobacz sekcję Więcej na temat zmiennych w Bash Guide dla początkujących i rozszerzaniu parametrów w specyfikacji POSIX.
Używanie cudzysłowów wokół zmiennej jak w rm -- "$VAR1"
lub rm -- "${VAR}"
jest dobrym pomysłem. To sprawia, że zawartość zmiennej jest jednostką atomową. Jeśli wartość zmiennej zawiera spacje (cóż, znaki w $IFS
zmiennej specjalnej, domyślnie spacje) lub znaki globowania, a nie zacytujesz, to każde słowo jest brane pod uwagę przy generowaniu nazw plików (globbing), których rozwinięcie daje tyle argumentów, co ty robię.
$ find .
.
./*r*
./-rf
./another
./filename
./spaced filename
./another spaced filename
./another spaced filename/x
$ var='spaced filename'
# usually, 'spaced filename' would come from the output of some command and you weren't expecting it
$ rm $var
rm: cannot remove 'spaced': No such file or directory
# oops! I just ran 'rm spaced filename'
$ var='*r*'
$ rm $var
# expands to: 'rm' '-rf' '*r*' 'another spaced filename'
$ find .
.
./another
./spaced filename
./another spaced filename
$ var='another spaced filename'
$ rm -- "$var"
$ find .
.
./another
./spaced filename
Przenośność: zgodnie z POSIX.1-2008 sekcja 2.6.2 nawiasy klamrowe są opcjonalne.
var1=$var
rozszerzenie powoduje błąd?export VAR=$VAR1
. Jeśli chodzi o nawiasy klamrowe, są one opcjonalne (sprawdź czwarty akapit cytowanej sekcji; dotyczy to wszystkich powłok wcześniejszych niż POSIX i POSIX).${VAR}
i$VAR
są dokładnie równoważne. W przypadku zwykłego rozszerzania zmiennych jedynym powodem jest użycie,${VAR}
gdy parsowanie w przeciwnym razie przyciągałoby zbyt wiele znaków do nazwy zmiennej, jak w${VAR1}_$VAR2
(co bez nawiasów byłoby równoważne${VAR1_}$VAR2
). Większość zdobione ekspansje (${VAR:=default}
,${VAR#prefix}
...) wymagają szelki.Przy przypisywaniu zmiennych dzielenie pól (tj. Dzielenie na białą wartość w wartości) i rozwijanie nazw ścieżek (tj. Globowanie) są wyłączone, więc
VAR=$VAR1
jest dokładnie równoważne zVAR="$VAR1"
, we wszystkich powłokach POSIX i we wszystkich wersjach wcześniejszych niż POSIX, o których słyszałem . (POSIX ref: proste polecenia ). Z tego samego powoduVAR=*
niezawodnie ustawiaVAR
ciąg literalny*
; oczywiścieVAR=a b
ustawia sięVAR
na,a
ponieważb
to przede wszystkim osobne słowo. Ogólnie rzecz biorąc, podwójne cudzysłowy są niepotrzebne, gdy składnia powłoki oczekuje pojedynczego słowa, na przykład wcase … in
(ale nie we wzorcu), ale nawet tam należy zachować ostrożność: na przykład POSIX określa, żecele przekierowania (>$filename
) nie wymagają cytowania w skryptach, ale kilka powłok, w tym bash, wymaga podwójnych cytatów nawet w skryptach. Zobacz Kiedy konieczne jest podwójne cytowanie? dla dokładniejszej analizy.W innych przypadkach potrzebujesz podwójnych cudzysłowów, w szczególności w
export VAR="${VAR1}"
(które można zapisaćexport "VAR=${VAR1}"
w równoważny sposób ) w wielu powłokach (POSIX pozostawia tę skrzynkę otwartą). Podobieństwo tego przypadku do prostych zadań i rozproszony charakter listy przypadków, w których nie potrzebujesz podwójnych cudzysłowów, dlatego właśnie zalecam stosowanie podwójnych cudzysłowów, chyba że chcesz podzielić i zsumować.źródło
IFS
znaków, ponieważ chcę mieć nawyk. Jedynym wyjątkiem jest to, że nie cytuję wartości podczas przypisywania zmiennej (chyba że jest to wymagane, na przykład gdy wartość zawiera spację). To sprawia, że podświetlanie składni edytora jest bardziej przydatne, gdy występują zastępowania poleceń, takie jakFOO=$(BAR=$(BAZ=blah; printf %s "${BAZ}"); printf %s "${BAR}")
. Zamiast kolorować wszystko kolorem „ciągowym”, podświetlam składnię zagnieżdżonego kodu. Dlatego też unikam uderzeń zwrotnych.>$file
jest dobrze w skryptach POSIX, nie jest bash, nawet gdy nie jest interaktywny (chyba że wymuszona jest zgodność z POSIX$POSIXLY_CORRECT
lub--posix
...).VAR=$VAR1
, czasami byłem zaskoczonylocal VAR=$VAR1
, co, jak pamiętam, działało inaczej pod pewnymi względami, przynajmniej w niektórych powłokach. Ale atm, nie mogę odtworzyć rozbieżności.local VAR=$VAR1
jest jakexport VAR=$VAR1
, to zależy od powłoki.Cytat
Weź pod uwagę, że podwójny cudzysłów służy do zmiennej interpretacji, a pojedynczy cudzysłów służy do silnego cytowania, tj. Bez rozszerzenia.
Ekspansja:
Wynik:
Warto wspomnieć, że w miarę możliwości należy stosować cytat z kilku powodów, między innymi z tego, że jest to uważane za najlepszą praktykę i ze względu na czytelność. Również dlatego, że Bash jest czasem dziwaczny i często z pozornie nielogicznych lub nieuzasadnionych / nieoczekiwanych sposobów, a cytowanie zmienia jawne oczekiwania, co zmniejsza jawną powierzchnię błędu (lub potencjalną możliwość wystąpienia).
I choć jest to całkowicie legalne nie cytować, i będzie działać w większości przypadków, że funkcjonalność jest dla wygody i jest prawdopodobnie mniej przenośne. cytowana jest w pełni formalna praktyka gwarantująca odzwierciedlenie zamiarów i oczekiwań.
Podstawienie
Teraz rozważ również, że konstrukcja
"${somevar}"
jest używana do operacji podstawienia. Kilka przypadków użycia, takich jak zamiana i tablice.Wymiana (stripping):
Wymiana (wymiana):
Tablice:
Wszystko to ledwo rysuje powierzchnię
"${var}"
konstruktu podstawienia. Ostatecznym odniesieniem dla skryptów powłoki Bash jest bezpłatne odniesienie online, TLDP The Linux Documentation Projecthttps://www.tldp.org/LDP/abs/html/parameter-substitution.html
źródło
koniec wtedy:
Warto wspomnieć o jaśniejszym przykładzie używania loków
źródło