ich kann schreiben
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
Das Endergebnis scheint mir alle ungefähr gleich zu sein. Warum soll ich den einen oder anderen schreiben? Sind einige davon nicht portabel / POSIX?
ich kann schreiben
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
Das Endergebnis scheint mir alle ungefähr gleich zu sein. Warum soll ich den einen oder anderen schreiben? Sind einige davon nicht portabel / POSIX?
Antworten:
VAR=$VAR1
ist eine vereinfachte Version von VAR=${VAR1}
. Es gibt Dinge, die der zweite tun kann, die der erste nicht kann, zum Beispiel einen Array-Index referenzieren (nicht portierbar) oder eine Teilzeichenfolge entfernen (POSIX-portierbar). Siehe die Mehr zu Variablen Abschnitt des Bash Leitfaden für Anfänger und Parameter Expansion in der POSIX - Spezifikation.
Die Verwendung von Anführungszeichen um eine Variable wie in rm -- "$VAR1"
oder rm -- "${VAR}"
ist eine gute Idee. Dies macht den Inhalt der Variablen zu einer atomaren Einheit. Wenn der Variablenwert Leerzeichen (also Zeichen in der $IFS
Sondervariable, standardmäßig Leerzeichen) oder Globenzeichen enthält und Sie ihn nicht in Anführungszeichen setzen, wird jedes Wort für die Generierung von Dateinamen (Globenzeichen) in Betracht gezogen, dessen Erweiterung beliebig viele Argumente liefert mache.
$ 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
Zur Portabilität: Gemäß POSIX.1-2008 Abschnitt 2.6.2 sind die geschweiften Klammern optional.
var1=$var
Erweiterung einen Fehler verursacht?
export VAR=$VAR1
. Die geschweiften Klammern sind optional (siehe den vierten Absatz des Abschnitts, den Sie zitiert haben; dies ist bei allen Schalen vor POSIX und POSIX der Fall).
${VAR}
und $VAR
sind genau gleichwertig. Für eine einfache Variablenerweiterung ist der einzige Grund zu verwenden, ${VAR}
wenn beim Parsen ansonsten zu viele Zeichen in den Variablennamen ${VAR1}_$VAR2
eingehen würden , wie in (was ohne geschweifte Klammern äquivalent wäre ${VAR1_}$VAR2
). Die meisten geschmückt Erweiterungen ( ${VAR:=default}
, ${VAR#prefix}
, ...) erfordern Klammern.
In einer Variablenzuweisung, Feldaufspaltung (dh Spaltung bei Leerraum im Wert) und Pfadnamenerweiterung (dh Globbing) ausgeschaltet sind, so VAR=$VAR1
genau entspricht VAR="$VAR1"
, in allen POSIX Muscheln und in alle pre-POSIX sh , die ich habe gehört , von . (POSIX ref: einfache Befehle ). Legt aus demselben Grund VAR=*
zuverlässig VAR
die Literalzeichenfolge fest *
. Natürlich VAR=a b
setzt VAR
auf , a
da das b
ist ein separates Wort an erster Stelle. Im Allgemeinen sind doppelte Anführungszeichen nicht erforderlich, wenn die Shell-Syntax ein einzelnes Wort erwartet, zum Beispiel incase … in
(aber nicht im Muster), aber auch dort müssen Sie vorsichtig sein: POSIX gibt dies zum Beispiel anUmleitungsziele ( >$filename
) erfordern keine Anführungszeichen in Skripten, aber einige Shells, einschließlich Bash, erfordern die doppelten Anführungszeichen sogar in Skripten. Siehe Wann sind doppelte Anführungszeichen erforderlich? für eine gründlichere Analyse.
Sie benötigen die doppelten Anführungszeichen in anderen Fällen, insbesondere in export VAR="${VAR1}"
(was äquivalent geschrieben werden kann export "VAR=${VAR1}"
) in vielen Shells (POSIX lässt diesen Fall offen). Aufgrund der Ähnlichkeit dieses Falls mit einfachen Zuweisungen und der Streuung der Liste der Fälle, in denen Sie keine doppelten Anführungszeichen benötigen, empfehle ich, nur doppelte Anführungszeichen zu verwenden, es sei denn, Sie möchten splitten und globieren.
IFS
Zeichen enthält, weil ich es mir zur Gewohnheit machen möchte. Die einzige Ausnahme ist, dass ich den Wert bei einer Variablenzuweisung nicht zitiere (sofern nicht erforderlich, z. B. wenn der Wert ein Leerzeichen enthält). Dies macht die Hervorhebung der Editor-Syntax nützlicher, wenn Befehlssubstitutionen wie z FOO=$(BAR=$(BAZ=blah; printf %s "${BAZ}"); printf %s "${BAR}")
. Anstatt alles in der "String" -Farbe zu färben, erhalte ich eine Syntaxhervorhebung des verschachtelten Codes. Deshalb vermeide ich auch Backticks.
>$file
in POSIX - Skripte in Ordnung ist, ist es in der Bash nicht einmal , wenn nicht-interaktive (es sei denn , POSIX Einhaltung erzwungen wird $POSIXLY_CORRECT
oder --posix
...).
VAR=$VAR1
, aber ich war manchmal überrascht local VAR=$VAR1
, weil ich mich erinnere, dass ich in mancher Hinsicht anders gearbeitet habe, zumindest in einigen Shells. Aber atm, ich kann die Divergenz nicht reproduzieren.
local VAR=$VAR1
ist wie export VAR=$VAR1
, es kommt auf die Shell an.
Bedenken Sie, dass für die variable Erweiterung das doppelte Anführungszeichen und für die starke Anführungszeichen, dh ohne Erweiterung, das einfache Anführungszeichen verwendet wird.
this='foo'
that='bar'
these="$this"
those='$that'
for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that
Es kann sinnvoll sein, zu erwähnen, dass Sie aus verschiedenen Gründen, wo immer möglich, Zitate verwenden sollten, von denen die besten sind, dass sie als Best Practice gelten, und aus Gründen der Lesbarkeit. Auch, weil Bash zuweilen skurril ist und häufig für unlogisch oder unvernünftig / unerwartet erscheinende Wege und das Ändern von impliziten Erwartungen zu explizit, was diese Fehlerfläche (oder das Potenzial dafür) reduziert.
Und obwohl es völlig legal ist, nicht zu zitieren, und in den meisten Fällen funktioniert, wird diese Funktionalität aus Bequemlichkeitsgründen bereitgestellt und ist wahrscheinlich weniger portabel. Die vollständig formale Praxis, die die Absicht und Erwartung widerspiegelt, ist das Zitieren.
Bedenken Sie nun auch, dass das Konstrukt "${somevar}"
für Substitutionsoperationen verwendet wird. Mehrere Anwendungsfälle, z. B. Ersatz und Arrays.
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
All dies kratzt kaum an der Oberfläche des "${var}"
Substitutionskonstrukts. Die endgültige Referenz für Bash-Shell-Skripte ist die libre-Online-Referenz 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
ende dann:
env=$1
if [ ! -f /dirname/${env}hostname ]
Erwähnenswert als klareres Beispiel für die Verwendung von Locken