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?
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?
Risposte:
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). Vedi la sezione Altro sulle variabili della Guida di Bash per principianti ed espansione dei parametri nelle specifiche POSIX.
Usare le 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 (beh, caratteri nella $IFS
variabile speciale, spazi vuoti per impostazione predefinita) o caratteri globbing e non li citate, allora ogni parola viene considerata per la generazione del nome file (globbing) la cui espansione rende altrettanti argomenti per qualsiasi cosa tu 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.
var1=$var
espansione genera un errore?
export VAR=$VAR1
. Per quanto riguarda le parentesi graffe, sono opzionali (controlla il quarto paragrafo della sezione che hai citato; questo è il caso in tutte le shell pre-POSIX e POSIX).
${VAR}
e $VAR
sono esattamente equivalenti. Per una semplice espansione variabile, l'unico motivo da utilizzare ${VAR}
è quando l'analisi analizzerebbe altrimenti troppi caratteri nel nome della variabile, come in ${VAR1}_$VAR2
(a cui senza parentesi sarebbe equivalente ${VAR1_}$VAR2
). Espansioni più ornati ( ${VAR:=default}
, ${VAR#prefix}
, ...) richiedono parentesi graffe.
In un'assegnazione variabile, la divisione del campo (ovvero la divisione nello spazio bianco nel valore) e l' espansione del nome del percorso (ovvero il globbing) sono disattivate, 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 lo stesso motivo, si VAR=*
imposta in modo affidabile VAR
sulla stringa letterale *
; ovviamente si VAR=a b
imposta VAR
su a
poiché b
in primo luogo è una parola separata. In generale, le virgolette doppie non sono necessarie quando la sintassi della shell prevede una sola parola, ad esempio incase … in
(ma non nel modello), ma anche lì è necessario fare attenzione: ad esempio POSIX specifica chei target di reindirizzamento ( >$filename
) non richiedono virgolette negli script, ma alcune shell tra cui bash richiedono le doppie virgolette anche negli script. Vedi Quando è necessaria la doppia citazione? per un'analisi più approfondita.
In altri casi sono necessarie le doppie virgolette, 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.
IFS
carattere perché voglio avere l'abitudine. L'unica eccezione è che non cito il valore quando si esegue un'assegnazione variabile (a meno che non sia richiesto, ad esempio quando il valore contiene uno spazio). Questo rende l'evidenziazione della sintassi dell'editor più utile quando ci sono sostituzioni di comandi come FOO=$(BAR=$(BAZ=blah; printf %s "${BAZ}"); printf %s "${BAR}")
. Invece di colorare tutto il colore "stringa", ottengo l'evidenziazione della sintassi del codice nidificato. Questo è anche il motivo per cui evito i backtick.
>$file
sia OK negli script POSIX, non è in bash anche quando non interattivo (a meno che la conformità POSIX sia imposta con $POSIXLY_CORRECT
o --posix
...).
VAR=$VAR1
, sono stato sorpreso a volte local VAR=$VAR1
, che ricordo di aver lavorato in modo diverso sotto alcuni aspetti, almeno in alcune conchiglie. Ma atm, non riesco a riprodurre la divergenza.
local VAR=$VAR1
è come export VAR=$VAR1
, dipende dalla shell.
Si consideri che la doppia virgoletta viene utilizzata per l'espansione variabile e la virgoletta singola viene utilizzata per le virgolette forti, ovvero l'espansione sans.
this='foo'
that='bar'
these="$this"
those='$that'
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 è completamente legale non quotare, e funzionerà nella maggior parte dei casi, tale funzionalità è fornita per comodità ed è probabilmente meno portatile. la pratica completamente formale garantita per riflettere l'intento e le aspettative è di citare.
Ora considera anche che il costrutto "${somevar}"
è usato per le operazioni di sostituzione. Diversi casi d'uso, come la sostituzione e le matrici.
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
Tutto questo a malapena graffia la superficie del "${var}"
costrutto di sostituzione. Il riferimento definitivo per gli script di shell Bash è il riferimento online gratuito, TLDP The Linux Documentation Projecthttps://www.tldp.org/LDP/abs/html/parameter-substitution.html
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