it-swarm.it

$ VAR vs $ {VAR} e per citare o non citare

Posso scrivere

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

il risultato finale per me sembra quasi lo stesso. Perché dovrei scrivere l'uno o l'altro? qualcuno di questi non è portatile/POSIX?

150
xenoterracide

VAR=$VAR1 è una versione semplificata di VAR=${VAR1}. Ci sono cose che il secondo può fare che il primo non può, ad esempio fare riferimento a un indice di array (non portatile) o rimuovere una sottostringa (POSIX-portatile). Vedere la sezione Altre informazioni sulle variabili della Guida di Bash per principianti e Espansione parametri nelle specifiche POSIX.

Utilizzo delle virgolette attorno a una variabile come in rm -- "$VAR1" o rm -- "${VAR}" è una buona idea. Questo rende il contenuto della variabile un'unità atomica. Se il valore della variabile contiene spazi vuoti (bene, i caratteri in $IFS variabile speciale, spazi vuoti per impostazione predefinita) o caratteri globbing e non lo citi, quindi ogni parola viene considerata per la generazione del nome file (globbing) la cui espansione rende altrettanti argomenti per tutto ciò che stai facendo.

$ 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

Sulla portabilità: secondo POSIX.1-2008 sezione 2.6.2 , le parentesi graffe sono opzionali.

108
Shawn J. Goff

${VAR} e $VAR sono esattamente equivalenti. Per una semplice espansione variabile, l'unico motivo per utilizzare ${VAR} è quando l'analisi altrimenti prenderebbe troppi caratteri nel nome della variabile, come in ${VAR1}_$VAR2 (che senza parentesi sarebbe equivalente a ${VAR1_}$VAR2). Espansioni più adornate (${VAR:=default}, ${VAR#prefix}, ...) richiedono parentesi graffe.

In un'assegnazione variabile, divisione del campo (ovvero divisione nello spazio bianco nel valore) e espansione del percorso (ovvero globbing) sono disattivati, quindi VAR=$VAR1 è esattamente equivalente a VAR="$VAR1", in tutte le shell POSIX e in tutte le sh pre-POSIX di cui ho sentito parlare. (Rif. POSIX: comandi semplici ). Per la stessa ragione, VAR=* imposta in modo affidabile VAR sulla stringa letterale *; ovviamente VAR=a b imposta VAR su a poiché b è innanzitutto una parola separata. In generale, le virgolette doppie non sono necessarie quando la sintassi di Shell prevede una singola parola, ad esempio in case … in (ma non nello schema), ma anche lì devi fare attenzione: ad esempio POSIX specifica che target di reindirizzamento (>$filename) non richiedono virgolette negli script, ma alcune shell tra cui bash richiedono le doppie virgolette anche negli script. Vedere Quando è necessaria la doppia virgoletta? per un'analisi più approfondita.

Hai bisogno delle doppie virgolette negli altri casi, in particolare in export VAR="${VAR1}" (che può essere equivalentemente scritto export "VAR=${VAR1}") in molte shell (POSIX lascia questo caso aperto). La somiglianza di questo caso con compiti semplici e la natura sparsa dell'elenco dei casi in cui non hai bisogno di virgolette doppie, sono il motivo per cui ti consiglio di usare solo virgolette doppie a meno che tu non voglia dividere e glob.

Quotazione

Considera che la doppia virgoletta viene utilizzata per l'espansione variabile e la virgoletta singola viene utilizzata per le virgolette forti, ovvero l'espansione sans.

Espansione:

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

Produzione:

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

Potrebbe essere utile menzionare che è necessario utilizzare la quotazione laddove possibile per diversi motivi, tra i quali i migliori sono considerati best practice e leggibilità. Anche perché Bash a volte è bizzarro e spesso per modi apparentemente illogici o irragionevoli/imprevisti, e la quotazione cambia le aspettative implicite in esplicite, il che riduce quella superficie di errore (o potenziale per ciò).

E mentre è del tutto legale non citare, e funzionerà nella maggior parte dei casi, tale funzionalità è fornita per comodità ed è probabilmente meno portabile. la pratica completamente formale garantita per riflettere l'intento e le aspettative è di citare.

Sostituzione

Ora considera anche che il costrutto "${somevar}" viene utilizzato per le operazioni di sostituzione. Diversi casi d'uso, come la sostituzione e le matrici.

Sostituzione (stripping):

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

Sostituzione (sostituzione):

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

Array:

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

Tutto questo a malapena graffia la superficie del "${var}" costrutto di sostituzione. Il riferimento definitivo per gli script di Bash Shell è il riferimento online gratuito, 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

fine quindi:

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

vale la pena ricordare come esempio più chiaro di utilizzo dei ricci

0
ninjabber