![]() |
![]() |
|
Hier ein einfaches Script, das Ihnen die Zahlenvergleiche in der Praxis demonstriert: # Demonstriert das test-Kommando mit Zahlenwerten # Name: avalue a=6; b=7 if [ $a -eq $b ] then echo "\$a ($a) ist gleich mit \$b ($b)" else echo "\$a ($a) ist nicht gleich mit \$b ($b)" fi if [ $a -gt $b ] then echo "\$a ($a) ist größer als \$b ($b)" elif [ $a -lt $b ] then echo "\$a ($a) ist kleiner als \$b ($b)" else echo "\$a ($a) ist gleich mit \$b ($b)" fi if [ $a -ne 5 ] then echo "\$a ($a) ist ungleich 5" fi if [ 7 -eq $b ] then echo "\$b ist gleich 7" fi Das Script bei der Ausführung: you@host > ./avalue $a (6) ist nicht gleich mit $b (7) $a (6) ist kleiner als $b (7) $a (6) ist ungleich 5 $b ist gleich 7 Dass hier tatsächlich numerische Zahlenvergleiche und keine String-Vergleiche stattfinden, ist den Ausdrücken –eq, –ne, –lt, –gt, –le und –ge zu verdanken. Steht einer dieser Ausdrücke zwischen zwei Zahlen, wandelt der Befehl test die Zeichenketten vorher noch in Zahlen um. Dabei ist das test-Kommando sehr »intelligent« und erkennt selbst folgende Werte als Zahlen an: you@host > a="00001"; b=1 you@host > [ $a -eq $b ] you@host > echo $? 0 you@host > a=" 1"; b=1 you@host > [ $a -eq $b ] you@host > echo $? 0 Hier wurde auch die Zeichenkette "00001" und " 1" von test in eine numerische 1 umgewandelt. Argumente aus der Kommandozeile überprüfenEine fast immer verwendete Aktion des test-Kommandos ist das Überprüfen, ob die richtige Anzahl von Argumenten in der Kommandozeile eingegeben wurde. Die Anzahl der Argumente finden Sie in der Variablen $# – mit dem test-Kommando können Sie jetzt entsprechend reagieren. # Überprüft die richtige Anzahl von Argumenten # aus der Kommandozeile # Name: atestarg if [ $# -ne 2 ] then echo "Hier sind mindestens 2 Argumente erforderlich" echo "usage: $0 arg1 arg2 ... [arg_n]" exit 1 else echo "Erforderliche Anzahl Argumente erhalten" fi Das Script bei der Ausführung: you@host > ./atestarg Hier sind mindestens 2 Argumente erforderlich usage: atestarg arg1 arg2 ... [arg_n] you@host > ./atestarg Hallo Welt Erforderliche Anzahl Argumente erhalten 4.4.2 Ganze Zahlen vergleichen mit let (Bash und Korn-Shell only)
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ausdruck | Operator | Liefert wahr (0) zurück, wenn ... |
| (( var1 == var2 )) | == | var1 gleich var2 ist |
| (( var1 != var2 )) | != | var1 ungleich var2 ist |
| (( var1 < var2 )) | < | var1 kleiner als var2 ist |
| (( var1 > var2 )) | > | var1 größer als var2 ist |
| (( var1 >= var2 )) | >= | var1 größer oder gleich var2 ist |
| (( var1 <= var2 )) | <= | var1 kleiner oder gleich var2 ist |
Wer sich vielleicht noch an den let-Abschnitt erinnert, dem dürfte auffallen, was wir hier haben – richtig, bei der doppelten Klammerung (( ... )) handelt es sich um nichts anderes als um eine symbolische Form für das let-Kommando, welches Sie bereits bei den Variablen mit arithmetischen Ausdrücken verwendet haben. Natürlich können Sie hierbei auch anstatt der doppelten Klammerung das Kommando let verwenden. So kann beispielsweise statt
if (( $a > $b ))
auch let verwendet werden:
if let "$a > $b"
Im Gegensatz zur Verwendung von –eq, –ne usw. sind die Leerzeichen bei den Zahlenvergleichen hier nicht von Bedeutung und können bei Bedarf unleserlich zusammengequetscht werden ;-). Des Weiteren kann, wie Sie von let vielleicht noch wissen, das $-Zeichen vor den Variablen beim Vergleich in doppelter Klammerung entfallen.
Wollen Sie bspw. aus dem Listing »atestarg« den Test, ob die richtige Anzahl von Argumenten in der Kommandozeile eingegeben wurde, umschreiben auf die alternative Schreibweise der Bash und Korn-Shell, so müssen Sie nur die Zeile
if [ $# -ne 2 ]
umschreiben in
if (( $# != 2 ))
Das Vergleichen von Zeichenketten mit test funktioniert ähnlich wie bei Zahlenwerten. Hierbei übergeben Sie dem Kommando test eine Zeichenkette, einen Operanden und eine weitere Zeichenkette. Auch hier müssen Sie wieder jeweils (mindestens) ein Leerzeichen dazwischen einschieben. In Tabelle 4.3 sind die Operatoren zum Vergleichen von Zeichenketten aufgelistet:
| Ausdruck | Operator | Liefert wahr (0) zurück, wenn ... |
| [ "$var1" = "$var2" ] | = | var1 gleich var2 ist |
| [ "$var1" != "$var2" ] | != | var1 ungleich var2 ist |
| [ –z "$var" ] | –z | var leer ist |
| [ –n "$var" ] | –n | var nicht leer ist |
|
Hinweis Auch wenn es nicht vorgeschrieben ist, sollten Sie bei einem test mit Zeichenketten diese immer zwischen zwei doppelte Anführungszeichen setzen. Dies hilft Ihnen zu vermeiden, dass beim Vergleich einer Variable, die nicht existiert oder kein "" enthält, Fehler auftreten. |
Auch hierzu ein einfaches Shellscript, das verschiedene Vergleiche von Zeichenketten durchführt.
# Demonstriert einfache Zeichenkettenvergleiche # ateststring name1=juergen name2=jonathan if [ $# -lt 1 ] then echo "Hier ist mindestens ein Argument erforderlich" echo "usage: $0 Zeichenkette" exit 1 fi if [ "$1" = "$name1" ] then echo "Hallo juergen" elif [ "$1" = "$name2" ] then echo "Hallo jonathan" else echo "Hier wurde weder $name1 noch $name2 verwendet" fi if [ -n "$2" ] then echo "Hier wurde auch ein zweites Argument verwendet ($2)" else echo "Hier wurde kein zweites Argument verwendet" fi if [ -z "$name3" ] then echo "Der String \$name3 ist leer oder existiert nicht" elif [ "$name3" != "you" ] then echo "Bei \$name3 handelt es sich nicht um \"you\"" else echo "Hier ist doch \"you\" gemeint" fi
Das Script bei der Ausführung:
you@host > ./ateststring Hier ist mindestens ein Argument erforderlich usage: ./ateststring Zeichenkette you@host > ./ateststring test Hier wurde weder juergen noch jonathan verwendet Hier wurde kein zweites Argument verwendet Der String $name3 ist leer oder existiert nicht you@host > ./ateststring juergen Hallo juergen Hier wurde kein zweites Argument verwendet Der String $name3 ist leer oder existiert nicht you@host > ./ateststring juergen wolf Hallo juergen Hier wurde auch ein zweites Argument verwendet (wolf) Der String $name3 ist leer oder existiert nicht you@host > name3=wolf you@host > export name3 you@host > ./ateststring jonathan wolf Hallo jonathan Hier wurde auch ein zweites Argument verwendet (wolf) Bei $name3 handelt es sich nicht um "you" you@host > export name3=you you@host > ./ateststring jonathan wolf Hallo jonathan Hier wurde auch ein zweites Argument verwendet (wolf) Hier ist doch "you" gemeint
Wer jetzt immer noch denkt, man könne mit den bisherigen Mitteln noch kein vernünftiges Shellscript schreiben, für den soll hier ein einfaches Backup-Script geschrieben werden. Das folgende Script soll Ihnen zwei Möglichkeiten bieten. Zum einen eine Eingabe wie:
you@host > ./abackup1 save $HOME/Shellbuch
Hiermit soll der komplette Inhalt vom Verzeichnis $HOME/Shellbuch mittels tar archiviert werden (mitsamt den Meldungen des kompletten Verzeichnisbaums). Das Backup soll in einem extra erstellen Verzeichnis mit einem extra erstellten Namen (im Beispiel einfach TagMonatJahr.tar, bspw. 21Feb2005.tar) erstellt werden (natürlich komprimiert).
Auf der anderen Seite soll es selbstverständlich auch möglich sein, den Inhalt dieser Meldungen, der archivierten Backup-Datei, zu lesen, was gerade bei vielen Backup-Dateien auf der Platte unverzichtbar ist. Dies soll mit einem Aufruf wie
you@host > ./abackup1 read $HOME/backup/21Feb2005.tar
erreicht werden. Mit grep hinter einer Pipe können Sie nun nach einer bestimmten Datei im Archiv suchen. Dies könnte man natürlich auch im Script extra einbauen. Aber der Umfang soll hier nicht ins Unermessliche wachsen. Hier ein einfaches, aber anspruchsvolles Backup-Script:
# Ein einfaches Backup-Script
# Name: abackup1
# Beispiel: ./abackup1 save Verzeichnis
# Beispiel: ./abackup1 read (backupfile).tar
BACKUPDIR=$HOME/backup
DIR=$2
if [ $# != 2 ]
then
echo "Hier sind 2 Argumente erforderlich"
echo "usage: $0 Option Verzeichnis/Backupfile"
echo
echo "Mögliche Angaben für Option:"
echo "save = Führt Backup vom kompletten Verzeichnis durch"
echo " Verzeichnis wird als zweites Argument angegeben"
echo "read = Liest den Inhalt eines Backupfiles"
echo " Backupfile wird als zweites Argument angegeben"
exit 1
fi
# Falls Verzeichnis für Backup nicht existiert ...
if ls $BACKUPDIR > /dev/null
then
echo "Backup-Verzeichnis ($BACKUPDIR) existiert"
elif mkdir $BACKUPDIR > /dev/null
then
echo "Backup-Verzeichnis angelegt ($BACKUPDIR)"
else
echo "Konnte kein Backup-Verzeichnis anlegen"
exit 1
fi
# Wurde save oder read als erstes Argument verwendet ...
if [ "$1" = "save" ]
then
set `date`
BACKUPFILE="$3$2$6"
if tar czvf ${BACKUPDIR}/${BACKUPFILE}.tar $DIR
then
echo "Backup für $DIR erfolgreich in $BACKUPDIR angelegt"
echo "Backup-Name : ${BACKUPFILE}.tar"
else
echo "Backup wurde nicht durchgeführt !!!"
fi
elif [ "$1" = "read" ]
then
echo "Inhalt von $DIR : "
tar tzf $DIR
else
echo "Falsche Scriptausführung!!!"
echo "usage: $0 option Verzeichnis/Backupfile"
echo
echo "Mögliche Angaben für Option:"
echo "save = Führt ein Backup eines kompletten Verzeichnisses durch"
echo " Verzeichnis wird als zweites Argument angegeben"
echo "read = Liest den Inhalt eines Backupfiles"
echo " Backupfile wird als zweites Argument angegeben"
fi
Das Script bei der Ausführung:
you@host > ./abackup1 save $HOME/Shellbuch ls: /home/you/backup: Datei oder Verzeichnis nicht gefunden Backup-Verzeichnis angelegt (/home/you/backup) tar: Entferne führende `/' von Archivnamen. home/you/Shellbuch/ home/you/Shellbuch/Planung_und_Bewerbung/ home/you/Shellbuch/Planung_und_Bewerbung/shellprogrammierung.doc home/you/Shellbuch/Planung_und_Bewerbung/shellprogrammierung.sxw home/you/Shellbuch/kap004.txt home/you/Shellbuch/Kap003.txt~ home/you/Shellbuch/kap004.txt~ ... Backup für /home/you/Shellbuch erfolgreich in /home/you/backup angelegt Backup-Name : 21Feb2005.tar you@host > ./abackup1 read $HOME/backup/21Feb2005.tar | \ > grep Kap002 home/tot/Shellbuch/Kap002.doc home/tot/Shellbuch/Kap002.sxw you@host > ./abackup1 read $HOME/backup/21Feb2005.tar | wc -l 50
Hier wurde ein Backup vom kompletten Verzeichnis $HOME/Shellbuch durchgeführt. Anschließend wurde mit der Option read und grep nach »Kap002« gesucht, welches hier in zweifacher Ausführung vorhanden ist. Ebenso einfach können Sie hiermit die Anzahl von Dateien in einem Archiv (hier mit wc –l) ermitteln.
In der Bash und der Korn-Shell stehen Ihnen noch weitere alternative Möglichkeit zur Verfügung, um Zeichenketten zu vergleichen (siehe Tabelle 4.4). Besonders interessant erscheint mir in diesem Zusammenhang, dass hiermit jetzt auch echte Mustervergleiche möglich sind.
| Ausdruck | Operator | Liefert wahr (0) zurück, wenn ... |
| [[ "$var1" == "$var2" ]] | == | var1 gleich var2 ist |
| [[ "$var1" != "$var2" ]] | != | var1 ungleich var2 ist |
| [[ –z "$var" ]] | –z | var leer ist |
| [[ –n "$var" ]] | –n | var nicht leer ist |
| [[ "$var1" > "$var2" ]] | > | var1 alphabetisch größer als var2 ist |
| [[ "$var1" < "$var2" ]] | < | var1 alphabetisch kleiner als var2 ist |
| [[ "$var" == pattern ]] | == | var entspricht dem Muster pattern |
| [[ "$var" != pattern ]] | != | var entspricht nicht dem Muster-Pattern |
Das wirklich sehr interessante Feature bei den Vergleichen von Zeichenketten in Bash und Korn-Shell ist die Möglichkeit, Muster beim Vergleich zu verwenden. Hierbei gilt es zu beachten, dass sich das Muster auf der rechten Seite befindet und nicht zwischen Anführungsstrichen stehen darf. Zur Verwendung von Mustern stehen Ihnen wieder die Metazeichen *, ? und [ ] zur Verfügung, deren Bedeutung und Verwendung Sie bereits in Abschnitt 1.10.6 kennen gelernt haben. Natürlich können Sie auch die Konstruktionen für alternative Muster nutzen, welche Sie in Abschnitt 1.10.8 verwendet haben. Hier ein Beispiel mit einfachen Mustervergleichen:
# Demonstriert erweiterte Zeichenkettenvergleiche # ateststring2 if [ $# -lt 1 ] then echo "Hier ist mindestens ein Argument erforderlich" echo "usage: $0 Zeichenkette" exit 1 fi if [[ "$1" = *ist* ]] then echo "$1 enthält die Textfolge \"ist\"" elif [[ "$1" = ?art ]] then echo "$1 enthält die Textfolge \"art\"" elif [[ "$1" = kap[0–9] ]] then echo "$1 enthält die Textfolge \"kap\"" else echo "Erfolgloser Mustervergleich" fi
Das Script bei der Ausführung:
you@host > ./ateststring2 Bauart Erfolgloser Mustervergleich you@host > ./ateststring2 zart zart enthält die Textfolge "art" you@host > ./ateststring2 kap7 kap7 enthält die Textfolge "kap" you@host > ./ateststring2 kapa Erfolgloser Mustervergleich you@host > ./ateststring2 Mistgabel Mistgabel enthält die Textfolge "ist"
Eine weitere interessante Erneuerung ist der Vergleich auf größer bzw. kleiner als. Hiermit werden Zeichenketten alphabetisch in lexikografischer Anordnung verglichen. Hierzu ein Script:
# Demonstriert erweiterte Zeichenkettenvergleiche # ateststring3 var1=aaa var2=aab var3=aaaa var4=b if [[ "$var1" > "$var2" ]] then echo "$var1 ist größer als $var2" else echo "$var1 ist kleiner als $var2" fi if [[ "$var2" < "$var3" ]] then echo "$var2 ist kleiner als $var3" else echo "$var2 ist größer als $var3" fi if [[ "$var3" < "$var4" ]] then echo "$var3 ist kleiner als $var4" else echo "$var3 ist größer als $var4" fi
Das Script bei der Ausführung:
you@host > ./ateststring3 aaa ist kleiner als aab aab ist größer als aaaa aaaa ist kleiner als b
An diesem Script können Sie sehr gut erkennen, dass hier nicht die Länge der Zeichenkette zwischen dem größer bzw. kleiner entscheidet, sondern das Zeichen, womit die Zeichenkette beginnt. Somit ist laut Alphabet das Zeichen a kleiner als das Zeichen b. Beginnen beide Zeichenketten mit dem Buchstaben a, wird das nächste Zeichen verglichen – eben so, wie Sie dies von einem Lexikon her kennen.
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.
| << zurück |
|
||||||||||||
|
||||||||||||
|
||||||||||||
Copyright © Rheinwerk Verlag GmbH 2005
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.