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?
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?
Odpowiedzi:
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 z VAR="$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 powodu VAR=*
niezawodnie ustawia VAR
ciąg literalny *
; oczywiście VAR=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ć.
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 jak FOO=$(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 zaskoczony local 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 jak export VAR=$VAR1
, to zależy od powłoki.
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.
this='foo'
that='bar'
these="$this"
those='$that'
for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that
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ń.
Teraz rozważ również, że konstrukcja "${somevar}"
jest używana do operacji podstawienia. Kilka przypadków użycia, takich jak zamiana i tablice.
thisfile='foobar.txt.bak'
foo="${thisfile%.*}" # removes shortest part of value in $thisfile matching after '%' from righthand side
bar="${thisfile%%.*}" # removes longest matching
for item in "$foo" "$bar"; do echo "$item"; done
foobar.txt
foobar
foobar='Simplest, least effective, least powerful'
# ${var/find/replace_with}
foo="${foobar/least/most}" #single occurrence
bar="${foobar//least/most}" #global occurrence (all)
for item in "$foobar" "$foo" "$bar"; do echo "$item"; done
Simplest, least effective, least powerful
Simplest, most effective, least powerful
Simplest, most effective, most powerful
mkdir temp
# create files foo.txt, bar.txt, foobar.txt in temp folder
touch temp/{foo,bar,foobar}.txt
# alpha is array of output from ls
alpha=($(ls temp/*))
echo "$alpha" # temp/foo.txt
echo "${alpha}" # temp/foo.txt
echo "${alpha[@]}" # temp/bar.txt temp/foobar.txt temp/foo.txt
echo "${#alpha}" # 12 # length of first element (implicit index [0])
echo "${#alpha[@]}" # 3 # number of elements
echo "${alpha[1]}" # temp/foobar.txt # second element
echo "${#alpha[1])" # 15 # length of second element
for item in "${alpha[@]}"; do echo "$item"; done
temp/bar.txt
temp/foobar.txt
temp/foo.txt
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