unterschied zwischen ${} und $ () im Shell-Skript

$ echo $(date)
Thu Jul 2 16:33:11 SGT 2015
$ echo ${date}

$ name=foo
$ echo $(name)
ksh: name:  not found

$ echo ${name}
foo

Scheint, wie ${variable} ist das gleiche wie $variable. während $() ist, einen Befehl auszuführen. Warum dann $ {}?

Author: Noob, 2015-07-02

3 answers

$(command) ist "Befehlsersetzung".  Wie Sie zu verstehen scheinen, läuft es die command, erfasst seine Ausgabe, und fügt das in die Befehlszeile ein, die die $(…); z. B.

$ ls -ld $(date +%B).txt
-rwxr-xr-x  1 Noob Noob    867 Jul  2 11:09 July.txt

${parameter} ist "Parametersubstitution".  Viele Informationen finden Sie auf der Manpage der Shell, bash (1), unter der Überschrift " Parameter Expansion":

${parameter}
    Der Wert von Parameter wird ersetzt.  Die Zahnspangen sind erforderlich wenn Parameter ein Positionsparameter ist mit mehr als einer Ziffer oder wenn dem Parameter ein Zeichen folgt was nicht als Teil seines Namens zu interpretieren ist.

Positionsparameter siehe" Positionsparameter ", unten.  In seiner häufigsten Verwendung, wie in den anderen Antworten, parameter ist ein Variablenname.  Das Formular ${…}, wie am Ende des obigen Absatzes angegeben, können Sie den Wert einer Variablen erhalten (dh $variable_name) und folgen Sie ihm sofort mit einem Buchstaben, einer Ziffer oder einem Unterstrich:

$ animal=cat
$ echo $animals
                                # No such variable as “animals”.
$ echo ${animal}s
cats
$ echo $animal_food
                                # No such variable as “animal_food”.
$ echo ${animal}_food
cat_food

Sie können dies auch mit Anführungszeichen tun:

$ echo "$animal"s
cats

Oder als Übung in Optionen können Sie eine zweite Variable verwenden:

$ plural=s
$ echo $animal$plural
cats

Aber das ist nur Schritt 1.  Der nächste Absatz auf der Manpage ist interessant, wenn auch etwas kryptisch:

Wenn das erste Zeichen des Parameters ist ein Ausrufezeichen (!), eine Ebene der variablen Indirektion wird eingeführt.  Bash verwendet den Wert von die Variable gebildet aus dem Rest von Parameter als Name der Variablen; Diese Variable wird dann erweitert und dieser Wert wird im Rest der Substitution verwendet, anstatt den Wert von Parameter selbst.  Dies wird als indirekte Erweiterung bezeichnet.     ...(Ausnahmen)...   Das Ausrufezeichen muss sofort der linken Klammer folgen um Indirektion einzuführen.

Ich bin mir nicht sicher, wie ich das klarer machen kann, außer durch Beispiel:

$ animal=cat
$ echo $animal
cat
$ cat=tabby
$ echo $cat
tabby
$ echo ${!animal}
tabby                           # If $animal is “cat”, then ${!animal} is $cat, i.e., “tabby”

Nennen wir das Schritt 1½.  Es gibt viele interessante Dinge, die Sie als Schritt 2 tun können:

$ animal=cat
$ echo ${#animal}
3                               # String length
$ echo ${animal/at/ow}
cow                             # Substitution

Du kannst keines dieser Dinge ohne die {...} zahnspange.

Positionsparameter

Betrachten Sie dies als Beispiel:

$ cat myecho.sh
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15
$ ./myecho.sh Hey diddle diddle, The cat and the fiddle, The cow jumped over the moon.
Hey diddle diddle, The cat and the fiddle, The Hey0 Hey1 Hey2 Hey3 Hey4 Hey5

Weil die Shell nicht versteht $10, $11, etc.  Es behandelt $10, als wäre es ${1}0.  Aber es versteht ${10}, ${11}, etc., wie in der Manpage erwähnt ("ein Positionsparameter mit mehr als einer Ziffer").

Aber schreibe nicht wirklich solche Skripte; es gibt bessere Möglichkeiten, mit langen Argumentlisten umzugehen.

Das Obige (zusammen mit vielen weiteren Formen von ${parameter…something_else} Konstrukte) werden in der Manpage der Shell, bash(1), ausführlicher diskutiert.

Ein Hinweis auf Anführungszeichen

Beachten Sie, dass Sie Shell-Variablen immer zitieren sollten es sei denn, Sie haben eine gute Grund, nicht zu, und du bist sicher du weißt, was du tust.  Im Gegensatz dazu können Zahnspangen wichtig sein, Sie sind nicht so wichtig wie Zitate.

$ filename="nursery rhyme.txt"
$ ls -ld ${filename}
ls: cannot access nursery: No such file or directory
ls: cannot access rhyme.txt: No such file or directory
$ ls -ld "$filename"
-rwxr-xr-x  1 Noob Noob   5309 Jul  2 11:09 nursery rhyme.txt

Das gilt auch für Positionsparameter (dh Befehlszeilenargumente; zB "$1") und auch Befehlsersetzung:

$ ls -ld $(date "+%B %Y").txt
ls: cannot access July: No such file or directory
ls: cannot access 2015.txt: No such file or directory
$ ls -ld "$(date "+%B %Y").txt"
-rwxr-xr-x  1 Noob Noob    687 Jul  2 11:09 July 2015.txt

Sehen Bash-Zitate unescaped auf Befehl substitution für eine kurze Abhandlung über die Interaktion zwischen Zitaten und $(...).

 56
Author: G-Man Says 'Reinstate Monica',
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2017-03-20 10:17:34

In Ihrem Beispiel sind $var und ${var} identisch. Geschweifte Klammern sind jedoch nützlich, wenn Sie die Variable in einer Zeichenfolge erweitern möchten:

    $ string=foo
    $ echo ${string}bar
      foobar
    $ echo $stringbar

    $ 

Daher bieten die geschweiften Klammern eine Möglichkeit, die Variable zu ersetzen, um den Namen der neuen Variablen zu erhalten, die selbst ersetzt werden soll.

 9
Author: MariusMatutiae,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2015-07-02 08:45:21

Ich sehe es normalerweise häufiger in Strings. So etwas wird nicht funktionieren:

var="a"
echo "$varRAW_STRING"

Aber das wird:

var="a"
echo "${var}RAW_STRING"

Wie Sie richtig gesagt haben, wird $() verwendet, um einen Befehl auszuführen:

dir_contents=$(ls)

Sie können auch Backticks verwenden, aber ich finde die $() vielseitiger. Zum einen können Backticks nicht (leicht) verschachtelt werden.

date_directory=`ls `date '+%Y-%m-%d'`` # Makes no sense
date_directory=$(ls $(date '+%Y-%m-%d')) # Much better
 4
Author: bytesized,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2015-07-09 17:04:13