2.4 Quotings und Kommando-Substitution
Jetzt zu einem längst überfälligen Thema, den Quotings, zu dem die Kommando-Substitution (oder Kommandoersetzung) ebenfalls gehört. Häufiger wurden in den Beispielen zuvor Quotings eingesetzt, ohne jemals genauer darauf eingegangen zu sein.
Quoting ist die englische Bezeichnung für verschiedene Anführungszeichen (Quotes). Generell unterscheidet man dabei zwischen Single Quotes ('), Double Quotes (") und den Back Quotes (`). Siehe dazu Tabelle 2.5:
Tabelle 2.5
Verschiedene Quotes
Zeichen
|
Bedeutung
|
'
|
Single Quote, einfaches Anführungszeichen
|
"
|
Double Quote, doppeltes Anführungszeichen (oder Gänsefüßchen)
|
`
|
Back Quote, Backtick, Gravis-Zeichen, umgekehrtes einfaches Anführungszeichen
|
2.4.1 Single und Double Quotings
Um den Sinn vom Quotings zu verstehen, wird folgende echo-Ausgabe verwendet:
you@host > echo *** Hier wird $SHELL ausgeführt ***
aawk acut ased bin chmlib-0.35.tgz datei.csv Desktop Documents gedicht.txt namen.txt
nummer.txt OpenOffice.org1.1 public_html Shellbuch zusammen.txt Hier wird /bin/bash
ausgeführt aawk acut ased bin chmlib-0.35.tgz datei.csv Desktop Documents
gedicht.txt namen.txt nummer.txt OpenOffice.org1.1 public_html Shellbuch zusammen.txt
Das war jetzt sicherlich nicht die gewünschte und erwartete Ausgabe. Da hierbei das Metazeichen * mehrmals verwendet wurde, werden für jedes Sternchen alle Dateinamen im Verzeichnis ausgegeben. Nach Ihrem Wissensstand könnten Sie dem Problem mit mehreren Backslash-Zeichen entgegentreten.
you@host > echo \*\*\* Hier wird $SHELL ausgeführt \*\*\*
*** Hier wird /bin/bash ausgeführt ***
Aber auf Dauer ist dies wohl eher umständlich und auch sehr fehleranfällig. Testen Sie das ganze Beispiel doch einmal, indem Sie den auszugebenden Text in Single Quotes stellen.
you@host > echo '*** Hier wird $SHELL ausgeführt ***'
*** Hier wird $SHELL ausgeführt ***
Daraus können Sie nun schlussfolgern, dass bei der Verwendung von Single Quotes die Metazeichen (hier *) ausgeschaltet werden. Aber im Beispiel wurde auch die Umgebungsvariable $SHELL ausgequotet. Wenn Sie also die Variablen im Klartext ausgeben wollen (mitsamt Dollarzeichen), dann könnten Sie dies mit Single Quotes erreichen. Die Single Quotes helfen Ihnen auch beim Multiplizieren mit dem Kommando expr.
you@host > expr 10 * 10
expr: Syntaxfehler
you@host > expr 10 \* 10
100
you@host > expr 10 '*' 10
100
Zurück zu unserer Textausgabe. Wollen Sie den Wert einer Variablen (im Beispiel SHELL) ebenfalls ausgeben lassen, dann sollten Sie Double Quotes verwenden.
you@host > echo "*** Hier wird $SHELL ausgeführt ***"
*** Hier wird /bin/bash ausgeführt ***
Es mag jetzt verwirrend sein, weshalb ein Double Quoting den Inhalt einer Variablen anzeigt, aber die Sonderbedeutung des Metazeichens * ausschließt. Dies liegt daran, dass Double Quotes alle Metazeichen ausschließen, bis auf das Dollarzeichen (also auch den Variablen), das Back Quote-Zeichen und den Backslash.
Leerzeichen und Zeilenumbrüche
Damit Sie für den Fall der Fälle beim Verwenden der Single und Double Quotings keine Formatierungsprobleme bei der Ausgabe bekommen, folgen noch ein paar Hinweise. Das Thema Leerzeichen wurde bereits kurz bei der Beschreibung des Befehls echo erwähnt.
you@host > echo Name ID-Nr. Passwort
Name ID-Nr. Passwort
Im Beispiel wurden zwar einige Leerzeichen verwendet, welche aber bei der Ausgabe nicht erscheinen. Vielleicht mag dies den einen oder anderen verwundern, aber auch Leerzeichen haben eine Sonderbedeutung. Ein Leerzeichen mag eben in einer Shell immer gern ein Trennzeichen zwischen zwei Befehlen sein. Um vom Zeichen die Trennung als Bedeutung zu lösen, müssen Sie auch hierbei Ouotings einsetzen.
you@host > echo 'Name ID-Nr. Passwort'
Name ID-Nr. Passwort
you@host > echo "Name ID-Nr. Passwort"
Name ID-Nr. Passwort
Selbstverständlich hält Sie keiner davon ab, nur diese Leerzeichen zu quoten.
you@host > echo Name' 'ID-Nr.' Passwort'
Name ID-Nr. Passwort
Ähnlich sieht dies bei einem Zeilenwechsel aus:
you@host > echo Ein Zeilenwechsel \
> wird gemacht
Ein Zeilenwechsel wird gemacht
you@host > echo 'Ein Zeilenwechsel \
> wird gemacht'
Ein Zeilenwechsel \
wird gemacht
you@host > echo 'Ein Zeilenwechsel
wird gemacht'
Ein Zeilenwechsel
wird gemacht
you@host > echo "Ein Zeilenwechsel
> wird gemacht"
Ein Zeilenwechsel
wird gemacht
you@host > echo "Ein Zeilenwechsel \
wird gemacht"
Ein Zeilenwechsel wird gemacht
Verwenden Sie bspw. das Backslash-Zeichen bei einem Zeilenwechsel in Single Quotes, so wird es außer Kraft gesetzt und wie ein normales Zeichen ausgegeben. Beim Double Quoting hingegen behält das Backslash-Zeichen weiterhin seine Sonderbedeutung beim Zeilenumbruch. Ansonsten wird bei der Verwendung von Single oder Double Quotes bei Zeilenbrüchen kein Backslash-Zeichen verwendet, um einen Zeilenumbruch auszugeben.
2.4.2 Kommando-Substitution – Back Quotes
Die Funktion einer Shell schlechthin ist die Kommando-Substitution. Ohne dieses Feature wäre die Shell-Programmierung wohl nur die Hälfte wert. Damit erst wird es möglich, das Ergebnis eines Kommandos in einer Variablen abzuspeichern statt eine Ausgabe auf dem Bildschirm (bzw. in einer Datei) vorzunehmen. In der Praxis gibt es zwei Anwendungen der Kommando-Substitution:
variable=`kommando`
grep `kommando` file oder grep suche `kommando`
Bei der ersten Variante wird die Ausgabe eines Kommandos in einer Variablen gespeichert. Bei der zweiten Version wird die Ausgabe eines Kommandos für ein weiteres Kommando verwendet. Die Shell erkennt eine solche Kommando-Substitution, indem ein Kommando oder mehrere Kommandos zwischen Back Quotes (`) eingeschlossen ist. Einfachstes und immer wieder verwendetes Beispiel ist das Kommando date:
you@host > datum=`date`
you@host > echo $datum
Mo Feb 7 07:16:43 CET 2005
you@host > tag=`date +%A`
you@host > echo "Heute ist $tag"
Heute ist Montag
Die Kommando-Substitution ist für Sie als Script-Programmierer sozusagen die Luft zum Atmen, weshalb Sie sehr gut beraten sind, sich intensiv damit zu beschäftigen. Daher ist es auch unbedingt notwendig, sich bei der Shell-Programmierung auch mit den Linux-UNIX-Kommandos zu befassen. Hier ein einfaches Shellscript dazu:
# Demonstriert die Kommando-Substitution
# Name : asubstit
tag=`date +%A`
datum=`date +%d.%m.%Y`
count=`ls -l | wc -l`
echo "Heute ist $tag der $datum"
echo "Sie befinden sich in $HOME (Inhalt: $count Dateien)"
Das Script bei der Ausführung:
you@host > ./asubstit
Heute ist Montag der 07.02.2005
Sie befinden sich in /home/tot (Inhalt: 17 Dateien)
Die Kommando-Substitution wird in der Praxis aber häufig auch noch anders verwendet als eben demonstriert. Man kann mithilfe der Back Quotes auch die Ausgabe eines Kommandos für ein weiteres Kommando verwenden. Damit erhält ein Kommando den Rückgabewert eines anderen Kommandos. Hört sich schlimmer an, als es ist.
you@host > echo "Heute ist `date +%A`"
Heute ist Montag
Im Beispiel können Sie sehen, dass die Kommando-Substitution auch zwischen Double Quotes ihre Bedeutung behält. Entmachten können Sie die Back Quotes wieder mit einem Backslash-Zeichen.
you@host > echo "Heute ist \`date +%A\`"
Heute ist 'date +%A'
In welcher Reihenfolge mehrere Kommando-Substitutionen ausgeführt werden, ermitteln Sie am besten selbst mit der Option –x für die Shell.
you@host > set -x
you@host > echo "Format1: `date` Format2: `date +%d.%m.%Y`"
++ date
++ date +%d.%m.%Y
+ echo 'Format1: Mo Feb 7 12:59:53 CET 2005 Format2: 07.02.2005'
Format1: Mo Feb 7 12:59:53 CET 2005 Format2: 07.02.2005
Hinweis Wie bei einer Pipe, geht auch bei einer Kommando-Substitution die Fehlermeldung verloren.
|
Anfänger kommen schnell auf den Gedanken, Kommando-Substitutionen mit Pipes gleichzusetzen. Daher folgendes Beispiel als Gegenbeweis:
you@host > find . -name "*.txt" | ls -l
Was hier gewollt ist, dürfte schnell ersichtlich sein. Es wird versucht, aus dem aktuellen Arbeitsverzeichnis alle Dateien mit der Endung ».txt« herauszufiltern und an die Standardeingabe von ls –l zu schieben. Bei der Ausführung wird Ihnen jedoch auffallen, dass ls –l die Eingaben von find total ignoriert. find hat hierbei keinerlei Wirkung. Selbiges mit einer Kommando-Substitution zeigt allerdings dann den gewünschten Effekt.
you@host > ls -l `find . -name "*.txt"`
Wenden Sie dieses Prinzip bspw. auf das Script »asubstit« an, lässt sich dieses auf zwei Zeilen Umfang reduzieren. Hier die neue Version von »asubstit«:
# Demonstriert die Kommando-Substitution
# Name : asubstit2
echo "Heute ist `date +%A` der `date +%d.%m.%Y`"
echo "Sie befinden sich in $HOME " \
"(Inhalt:`ls -l | wc -l` Dateien)"Bei der Ausführung verläuft das Script »asubtit2« analog zu »asubstit«.
Erweiterte Syntax (Bash und Korn-Shell only)
Bash und Korn-Shell bieten Ihnen neben den Back Quotes außerdem noch eine andere Syntax an. Statt bspw.
you@host > echo "Heute ist `date`"
Heute ist Mo Feb 7 13:21:43 CET 2005
you@host > count=`ls -l | wc -l`
you@host > echo $count
18
you@host > ls -l `find . -name "*.txt"`
können Sie hier folgende Syntax verwenden:
you@host > echo "Heute ist $(date)"
Heute ist Mo Feb 7 13:24:03 CET 2005
you@host > count=$(ls -l | wc -l)
you@host > echo $count
18
you@host > ls -l $(find . -name "*.txt")
Die Verwendung von $(...) gegenüber `...` hat natürlich nur einen rein optischen Vorteil. Die Form $(...) lässt sich erheblich einfacher lesen, aber wem nützt das was, wenn es die Bourne-Shell nicht kennt. Wer sich sicher sein kann, dass seine Scripts auch immer in einer Bash oder einer Korn-Shell ausgeführt werden, der kann sich frohen Herzens damit anfreunden. Damit fällt wenigstens bei der Quoterei die Back Quote weg, und Sie müssen nur noch die Single und Double Quotes beachten.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.
|