it-swarm-eu.dev

$ VAR vs $ {VAR} a citovat či ne citovat

Umím psát

VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"

konečný výsledek se mi zdá stejný. Proč bych měl psát jeden nebo druhý? nejsou některé z nich přenosné/POSIX?

150
xenoterracide

VAR=$VAR1 je zjednodušená verze VAR=${VAR1}. Existují věci, které druhý může udělat, a ten první nemůže, například odkazovat na index pole (není přenosný) nebo odstranit podřetězec (přenosný POSIX). Viz část Více o proměnných v Průvodci Bash pro začátečníky a Rozšíření parametrů ve specifikaci POSIX.

Použití uvozovek kolem proměnné jako v rm -- "$VAR1" nebo rm -- "${VAR}" je dobrý nápad. Díky tomu je obsah proměnné atomovou jednotkou. Pokud hodnota proměnné obsahuje mezery (dobře, znaky v $IFS speciální proměnná, ve výchozím nastavení mezery) nebo globbingové znaky, které necitujete, pak každé slovo je považováno za generování názvu souboru (globbing), jehož rozšíření vytváří tolik argumentů, co děláte.

$ 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

O přenositelnosti: Podle POSIX.1-2008 oddíl 2.6.2 jsou složené závorky volitelné.

108
Shawn J. Goff

${VAR} a $VAR jsou přesně ekvivalentní. Pro jednoduché proměnné rozšíření je jediným důvodem použití ${VAR} je, když by analýza jinak chytila ​​příliš mnoho znaků do názvu proměnné, jako v ${VAR1}_$VAR2 (což by bez rovnátka odpovídalo ${VAR1_}$VAR2). Nejvíce zdobené rozšíření (${VAR:=default}, ${VAR#prefix},…) Vyžadují rovnátka.

Při variabilním přiřazení jsou rozdělení pole (tj. Rozdělení na bílé místo v hodnotě) a rozšíření názvu cesty (tj. Globbing) vypnuté, takže VAR=$VAR1 je přesně ekvivalentní s VAR="$VAR1", ve všech POSIXových skořápkách a ve všech pre-POSIXových shastech, o kterých jsem slyšel. (POSIX odkaz: jednoduché příkazy ). Ze stejného důvodu, VAR=* spolehlivě nastaví VAR na doslovný řetězec *; samozřejmě VAR=a b nastaví VAR na a, protože b je na prvním místě samostatné slovo. Obecně řečeno, dvojité uvozovky jsou zbytečné, pokud syntaxe Shell očekává jediné slovo, například v case … in (ale ne ve vzoru), ale i tam musíte být opatrní: například POSIX uvádí, že cíle přesměrování (>$filename) nevyžadují citace ve skriptech, ale několik shellů včetně bash vyžaduje dvojité uvozovky i ve skriptech. Podrobnější analýzu viz Kdy je nutná dvojitá nabídka? .

Dvojité uvozovky potřebujete v jiných případech, zejména v export VAR="${VAR1}" (které lze rovnocenně napsat export "VAR=${VAR1}") v mnoha nábojích (POSIX ponechává tento případ otevřený). Podobnost tohoto případu s jednoduchými úkoly a rozptýlená povaha seznamu případů, kdy nepotřebujete dvojité uvozovky, jsou důvodem, proč doporučuji používat pouze dvojité uvozovky, pokud se nechcete rozdělit a glob.

Citát

Uvažujte, že dvojitá nabídka se používá pro variabilní expanzi, a jednoduchá nabídka se používá pro silnou citaci, tj. Bez sans expanze.

Rozšíření:

this='foo'
that='bar'
these="$this"
those='$that'

Výstup:

for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that

Může být užitečné zmínit, že byste měli používat nabídku, kdykoli je to možné, z několika důvodů, mezi nejlepší z nich patří to, že je to považováno za nejlepší postup, a kvůli čitelnosti. Také proto, že Bash je občas nepředvídatelný a často pro zdánlivě nelogické nebo nepřiměřené/neočekávané způsoby, a citace mění implicitní očekávání na explicitní, což redukuje tuto chybovou plochu (nebo potenciální pro ni).

A přestože je zcela legální ne citovat, a ve většině případů bude fungovat, tato funkce je poskytována pro pohodlí a je pravděpodobně méně přenosná. plně formální praxe zaručená odrážet záměr a očekávání je citovat.

Náhrada

Nyní také zvažte, že konstrukce "${somevar}" se používá pro substituční operace. Několik případů použití, jako je nahrazení a pole.

Výměna (odizolování):

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

Výměna (výměna):

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

Pole:

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

To vše sotva poškrábe povrch "${var}" substituční konstrukt. Definitivním referenčním materiálem pro skriptování Bash Shell je online online odkaz, TLDP The Linux Documentation Project https://www.tldp.org/LDP/abs/html/parameter-substitution.html

9
SYANiDE
ls -la

lrwxrwxrwx.  1 root root      31 Nov 17 13:13 prodhostname
lrwxrwxrwx.  1 root root      33 Nov 17 13:13 testhostname
lrwxrwxrwx.  1 root root      32 Nov 17 13:13 justname

konec:

env=$1
    if [ ! -f /dirname/${env}hostname ]

stojí za zmínku jako jasnější příklad použití curlies

0
ninjabber