Kornshell
Die Kornshell (Eigenschreibweise KornShell, auch als ksh, ksh86, ksh88 und ksh93 bezeichnet) ist ein von David Korn entwickelter Kommandozeileninterpreter wie auch die Beschreibung der Skriptsprache, welche durch diesen Interpreter implementiert wird. Ursprunglich fur UNIX geschrieben finden sich heute Implementierungen nicht nur fur UNIX-ahnliche Systeme, sondern auch fur Windows und AmigaOS.
Die Sprachbeschreibung selbst ist gemeinfrei, jedoch nicht jede Implementierung. Der originale Quelltext der ksh93 ist seit 2000 (bzw. 2005, siehe Geschichte) ebenfalls gemeinfrei.
Die KornShell (in der Version von 1988) bildete die Grundlage fur die POSIX-Shell-Spezifikation und erfullt den POSIX2-Standard.[1] Sie ist vollstandig abwartskompatibel mit der Bourne-Shell (sh) und ubernimmt viele Neuerungen der C-Shell (csh).
Geschichte
[Bearbeiten | Quelltext bearbeiten]Die KornShell - so die durch ihren Autor gepragte Schreibung[2] - wurde Anfang der 1980er Jahre von David Korn bei den Bell Labs der AT&T entwickelt und bei der USENIX-Konferenz am 14. Juli 1983 vorgestellt.[3] Sie basierte ursprunglich auf einem Formularinterpreter, an dem David Korn mitgearbeitet hatte. Dessen Syntax wurde auf Basis der Bourne Shell konzipiert, unterschied sich von dieser aber durch wesentliche Verbesserungen: Job Control, eine der C Shell nachempfundene Command History und Command Aliasing.
ksh86
[Bearbeiten | Quelltext bearbeiten]Die neue Shell fand bei den Mitarbeitern von AT&T schnell Verbreitung, so dass sie schnell zur dortigen De-facto-Standardshell wurde. Da immer mehr Entwickler, die das Unternehmen verliessen, nach der Verfugbarkeit ausserhalb AT&Ts fragten, wurde die Shell schliesslich als Teil des UNIX System Toolchests gegen Gebuhr freigegeben. Die ksh86 war eine der ersten so veroffentlichten Versionen[4] und diente unter anderem als Vorbild fur die Shell fruher Versionen von QNX.[5]
ksh88
[Bearbeiten | Quelltext bearbeiten]Die Nachfolgeversion ksh88 wurde rasch zum Erfolg und wird heute noch von vielen Anbietern von Unix-Systemen ausgeliefert: HP-UX etwa hat eine eigene Version als Default-Shell, ebenso wird AIX (ab Version 4)[6][7] mit einer originalen ksh88 als Default-Shell ausgeliefert. Ende der 1980er-Jahre wurde die Spezifikation ksh88 festgelegt, welche die Grundlage fur die Beschreibung des Command Interpreters im POSIX-Standard bildete und im Wesentlichen mit dieser identisch ist. Die Rechte an der ksh88 liegen bei AT&T sowie bei Novell.
ksh93
[Bearbeiten | Quelltext bearbeiten]1993 erfolgte eine grundlegende Uberarbeitung der Shell wie auch ihrer Skriptsprache. Diese neue Spezifikation (bzw. Implementierungen, die ihr folgen) wird als ksh93 bezeichnet. Einzelne Versionen werden dabei durch angehangte Buchstaben gekennzeichnet, so ist etwa die aktuelle Version ksh93u+, welche der Version ksh93u, ksh93t+ und deren Vorgangerin ksh93t folgte.
Bis zum Jahr 2000 war die KornShell proprietare Software, die Rechte lagen bei AT&T und Lucent Technologies. 2000 wurde schliesslich der Quellcode veroffentlicht, erst unter einer AT&T-eigenen Version einer gemeinfreien Lizenz, ab Version ksh93q (2005) unter der Common Public License.[8]
Die KornShell und ihr Umfeld
[Bearbeiten | Quelltext bearbeiten]Unterschiede zu und Gemeinsamkeiten mit anderen Shells
[Bearbeiten | Quelltext bearbeiten]Commandline Editing, File Name Completion
[Bearbeiten | Quelltext bearbeiten]Eine der wichtigsten Anderungen gegenuber ihrer Vorgangerin, der Bourne-Shell, war die Moglichkeit, die eingegebene Kommandozeile zu wiederholen, beziehungsweise, vor dem erneuten Ausfuhren zu verandern. Diese Funktion wurde aus der C Shell Bill Joys ubernommen, aber gegenuber dieser wesentlich ausgebaut; in der ksh standen von Beginn an drei Editiermodi zur Verfugung, die alle das Verhalten gangiger Editoren nachahmten: vi, Emacs und XEmacs.
Ebenfalls neu war die Moglichkeit, Dateinamen automatisch vervollstandigen oder sich zu einem unvollstandig eingegebenen Dateinamen wahrend der Kommandoeingabe eine Liste aller passenden Dateien anzeigen zu lassen.
Mit der ksh93 wurde zusatzlich zur File Name Completion auch die Command Completion, also die Vervollstandigung unvollstandig angegebener, ausfuhrbarer Dateien, eingefuhrt. Diese Funktion ist mit jener der bash identisch.
Behandlung von Pipelines
[Bearbeiten | Quelltext bearbeiten]Im Gegensatz zur bash werden Pipelines in der ksh nicht automatisch in Subshells ausgefuhrt. Das hat gravierende Konsequenzen fur den Gultigkeitsbereich von Variablen:
typeset -i linenum=0
typeset line=""
cat /path/to/input | while read line ; do
(( linenum += 1 ))
done
echo $linenum
exit 0
In bash wurde die letzte Zeile 0 ausgeben, weil die while..done-Schleife als Bestandteil einer Pipeline in einer Subshell ausgefuhrt wird und $linenum deshalb nur in dieser Subshell inkrementiert wird. In einer KornShell hingegen wird die Anzahl der Zeilen in der Datei ausgegeben. Viele Nachbauten (etwa pdksh) realisieren dieses Verhalten allerdings nicht, sondern verhalten sich in dieser Hinsicht wie bash.
FPATH-Variable
[Bearbeiten | Quelltext bearbeiten]Seit ihren ersten Versionen verfugt die ksh uber die Systemvariable FPATH, die einen Standard-Suchpfad fur Dateien, welche Shell-Funktionen enthalten, definiert, analog der Variablen PATH fur ausfuhrbare Dateien. Dies ermoglicht den Aufbau von Funktionsbibliotheken, die sich ahnlich wie Shared Libraries verhalten. Dies ist ein grosser Vorteil gegenuber anderen Shells, insbesondere bash, die alle zu verwendenden Funktionen bei Skriptstart einparsen muss.
Floating-Point-Unterstutzung
[Bearbeiten | Quelltext bearbeiten]Die ksh93 verfugt zusatzlich zur gewohnlichen Integer-Arithmetik auch uber den Datentyp Floating-Point und die zugehorigen Methoden zur Bearbeitung solcher Daten.
Coprocess-Facility
[Bearbeiten | Quelltext bearbeiten]Eine unter den verbreiteten Shells einzigartige Funktion ist die Fahigkeit, sowohl der ksh88 wie auch ksh93, Hintergrundprozesse asynchron abzuarbeiten und dennoch uber Nachrichten zu steuern - das sogenannte Coprocess Facility. Dabei wird ein Prozess zwar im Hintergrund asynchron abgearbeitet, bleibt aber mit dem Vaterprozess uber zwei Datenkanale (ausgefuhrt als File-Deskriptoren 4 und 5) verbunden und kann uber diesen bidirektionalen Kanal gesteuert werden.
Varianten
[Bearbeiten | Quelltext bearbeiten]Nicht zuletzt wegen der ursprunglich lizenzbelasteten Situation wurden im Laufe der Zeit verschiedene Implementierungen der Korn Shell geschrieben, die mehr oder weniger kompatibel zur originalen Shell waren bzw. sind.
dtksh
[Bearbeiten | Quelltext bearbeiten]dtksh (Desktop ksh) ist eine Version der ksh93 zur Programmierung graphischer Oberflachen unter X11. Diese Version erweitert die ursprungliche Skriptsprache um Anbindungen zum Common Desktop Environment bzw. Motif, X, Xt und tcl.
pdksh / mksh / oksh
[Bearbeiten | Quelltext bearbeiten]pdksh ist eine gemeinfreie Implementierung der Korn Shell, die allerdings in einigen Punkten wenig Kompatibilitat aufweist (etwa werden Pipelines analog der bash und im Gegensatz zu allen ksh-Versionen in Subshells ausgefuhrt). Es werden die meisten Merkmale der ksh88 und einige wenige der ksh93 unterstutzt. Zusatzlich bringt sie einige eigene Erweiterungen mit.
mksh ist ein pdksh-Derivat, bei dem auf einfachere Bedienbarkeit und schlanken, aber korrekten Code Wert gelegt wird. Dabei werden auch Verbesserungen von Projekten wie Debian und OpenBSD eingepflegt. Im Gegensatz zur OpenBSD-ksh ist mksh portabel und steht fur verschiedene Plattformen zur Verfugung. Das Programm enthalt auch viele Erweiterungen und Detailverbesserungen (zum Beispiel unbegrenzt grosse Arrays oder ~/.mkshrc-Unterstutzung), verzichtet jedoch bewusst auf den Code aufblahende Funktionalitaten wie eine bash-artige $PS1-Syntax; auch ist es nicht als Ersatz fur /bin/sh gedacht. mksh wird vom MirOS-Projekt gewartet.
oksh ist eine Linux-Portierung der OpenBSD-Variante der Korn Shell, wobei im OpenBSD-Code nur so viel Anderungen wie notig eingepflegt werden, um ihn unter Linux kompilierbar zu machen. Diese Variante wird als Standard-Shell /bin/sh unter DeLi Linux eingesetzt.
Portierungen auf AmigaOS und Microsoft Windows
[Bearbeiten | Quelltext bearbeiten]SKsh ist eine Version fur AmigaOS, die eine Anzahl Amiga-spezifischer Merkmale wie beispielsweise ARexx-Interoperabilitat bietet.[9] In dieser Tradition ist die Kornshell Standard im Software Development Kit fur MorphOS.
Die MKS Korn Shell ist eine weitere kommerzielle Korn Shell-Implementierung. Sie ist Bestandteil von Microsofts Windows Services for UNIX (SFU) sowie dem Subsystem fur UNIX-basierte Anwendungen (SUA) der Windows Vista Enterprise und Ultimate Editionen. Dass sie erhebliche Mangel in der Kompatibilitat aufweist, wurde auf einer USENIX-Konferenz drastisch festgestellt. Die sich darum rankende Anekdote (hier wiedergegeben in den Worten David Korns) ging in die Geschichte ein:
"It was at a USENIX Windows NT conference and Microsoft was presenting their future directions for NT. One of their speakers said that they would release a UNIX integration package for NT that would contain the Korn Shell.
I knew that Microsoft had licensed a number of tools from MKS so I came to the microphone to tell the speaker that this was not the "real" Korn Shell and that MKS was not even compatible with ksh88. I had no intention of embarrassing him and thought that he would explain the compromises that Microsoft had to make in choosing MKS Korn Shell. Instead, he insisted that I was wrong and that Microsoft had indeed chosen a "real" Korn Shell. After a couple of exchanges, I shut up and let him dig himself in deeper. Finally someone in the audience stood up and told him what almost everyone in the audience knew, that I had written the 'real' Korn Shell. I think that this is symbolic about the way the company works."
,,Es geschah auf einer USENIX-Windows-NT-Konferenz und Microsoft prasentierte die weitere Entwicklung, die NT nehmen sollte. Einer ihrer Sprecher sagte, sie wurden ein UNIX-Integrationspaket auf den Markt bringen und es wurde eine KornShell enthalten.
Ich wusste, Microsoft hatte Lizenzen fur einige Tools von MKS gekauft, deshalb kam ich zum Mikrofon und erklarte dem Sprecher, dass das keine ,,echte" KornShell und dass MKS nicht einmal kompatibel mit der ksh88 sei. Ich hatte nicht die Absicht, ihn blosszustellen, und erwartete, dass er nun die Kompromisse erklaren wurde, die Microsoft eingegangen war, indem sie die MKS Korn Shell wahlten. Stattdessen bestand er darauf, dass ich daneben lage und dass Microsoft naturlich eine ,,echte" KornShell verwendete. Nach einigem Hin und Her schwieg ich und uberliess es ihm, sich immer tiefer hineinzureiten. Schlussendlich stand jemand im Publikum auf und sagte ihm, was fast alle Zuhorer wussten: namlich, dass ich die echte KornShell geschrieben hatte. Ich denke, das ist beispielhaft dafur, wie diese Firma arbeitet."
Einfuhrung in die Scriptsprache KornShell
[Bearbeiten | Quelltext bearbeiten]Die KornShell war von Beginn an, insbesondere aber die ksh93, in erster Linie als Script-Interpreter und erst in zweiter Linie als interaktive Shell gedacht.[11] Die folgende Einfuhrung geht auf die Unterschiede zwischen ksh88 und ksh93 nur am Rande ein, sondern versucht, die Eigentumlichkeiten der Programmiersprache KornShell uberhaupt herauszuarbeiten.
Kommentare
[Bearbeiten | Quelltext bearbeiten]Die KornShell kennt nur eine Form von Kommentar: ab dem Rautezeichen gilt alles bis zum Ende der Zeile als Kommentar, was dem // in C++ entspricht. Zeilenubergreifende Kommentare gibt es nicht.
Eine besondere Form von Kommentar ist der Shebang, der das ausfuhrende Programm festlegt, aber dies ist eine Leistung des Kernels. Fur die Shell ist dies ein Kommentar wie jeder andere auch. Soll das Rautezeichen als Literal verwendet werden, so muss es in Anfuhrungszeichen eingeschlossen oder escapet (durch ein vorangehendes Backslash-Zeichen '\' seiner besonderen Funktion entkleidet) werden.
#!/usr/bin/ksh# Dies ist ein Kommentar
print - "Hello World." # Kommentar: fuhre print-Statement aus
print - "#" # Doppelkreuz in Anfuhrungszeichen wird als Zeichen interpretiert
print - \# # escapetes Doppelkreuz
exit 0
Positionale und benannte Variablen, Here-Documents
[Bearbeiten | Quelltext bearbeiten]Variablen werden in der KornShell wie schon in der Bourne-Shell durch ein Dollarzeichen ('$') und einen in geschweifte Klammern eingeschlossenen Bezeichner angesprochen (die geschweiften Klammern konnen in manchen Fallen auch weggelassen werden). Bei der Zuweisung allerdings wird lediglich der Bezeichner verwendet.
#!/usr/bin/kshtypeset variable="Hello World." # Zuweisung
print - ${variable} # Verwendung der Variablen
print - $variable # Verwendung, alternative Form
exit 0
Benannte Variablen entsprechen dem, was in anderen Hochsprachen als Variablen bezeichnet wird: ein Bezeichner, der einen Speicherplatz referenziert, in welchem ein Wert abgelegt sein kann. Die KornShell erfordert dabei - zum Unterschied von anderen Hochsprachen - keine formale Deklaration und verlangt auch keine explizite Typisierung. Gleichwohl kann - und soll(!), schon im Sinne der Lesbarkeit und Dokumentation - mittels des Schlusselwortes typeset eine Deklaration samt Datentyp erfolgen, insbesondere dann, wenn dieser von String abweicht. Als Datentypen stehen zur Verfugung:
- String
- Integer
- Float (nur
ksh93) - Compound (nur
ksh93) - Array
Daruber hinaus kann jede Variable, unabhangig vom Typ, als String verwendet werden. Diese Variablen zeichnen sich dadurch aus, dass sie Namen tragen, weshalb sie benannte Variablen genannt werden.
Daneben gibt es unbenannte, sogenannte positionale Variablen, die automatisch im Falle von Scripten mit den ubergebenen Kommandozeilen-Parametern, im Falle von Shell-Funktionen mit den ubergebenen Argumenten gefullt werden. Sie werden mit Zahlen bezeichnet (${0}, ${1}, ${2} usw.), wobei ${0} immer den Namen des Programms bzw. der Funktion enthalt.
Mit Ausnahme von $0 konnen positionale Variablen mit dem Keyword shift abgearbeitet werden. shift loscht den Inhalt der Variablen $1 und belegt dann $1 mit dem Wert von $2, $2 mit dem Wert von $3 .. $n-1 mit dem Wert von $n:
print - "Name des Scripts............: ${0}"
print - "Erstes ubergebenes Argument : ${1}"
print - "Zweites ubergebenes Argument: $2" # alternativ auch ohne Klammern
print - "Drittes ubergebenes Argument: $3"
shift
print - "Erstes ubergebenes Argument : $1 (war vorher $2)"
print - "Zweites ubergebenes Argument: $2 (war vorher $3)"
print - "Drittes ubergebenes Argument: $3 (war vorher $4)"
exit 0
In Verbindung mit einer Schleife kann so eine bei Programmerstellung unbekannte Anzahl von ubergebenen Parametern stuckweise abgearbeitet werden.
Eine lediglich in manchen Shell-Sprachen anzutreffende Besonderheit ist das Here-Document. Es ist ein mit einem feststehenden Text gefullter String, der aber nicht wie eine Variable deklariert, sondern lediglich einmalig, z. B. als Input eines Kommandos, verwendet wird. Allerdings konnen innerhalb eines Here-Documents Variablen verwendet werden, die bei Ausfuhrung des Scripts durch ihre Inhalte ersetzt werden.
#!/usr/bin/kshtypeset chMsg="Hello World."
mail recipient@remote.system.com <
der Text der Nachricht lautet: $chMsg
EOF
exit 0
Alles zwischen den Begrenzern EOF (die Begrenzer sind frei wahlbare Bezeichner) wird als Eingabe an das Kommando mail geschickt, $chMsg wird durch den oben zugewiesenen Wert der Variablen ersetzt. In anderen Hochsprachen entsprechen den Here-Documents am ehesten String-Literale, in C++ etwa Raw String Literals.
Schleifen, Verzweigungen
[Bearbeiten | Quelltext bearbeiten]Schleifen und Verzweigungen sind kompatibel mit denen der Bourne Shell, von der sie bezogen sind. Die KornShell stellt drei Arten von Schleifen zur Verfugung: for, while und until.
Die for-Schleife entspricht im Verhalten dem von anderen Programmiersprachen Gewohnten: eine Liste von Werten wird iterierend einer Schleifenvariablen zugewiesen und jeweils ein Durchlauf des Schleifen-Korpers mit diesem Wert ausgefuhrt.
do
Liste von Kommandos
done
Im Unterschied zu den meisten Sprachen werden allerdings keine Zahlen-Werte (Integer) iteriert, sondern Strings, die aus einer feststehenden Liste entnommen werden. Diese feststehende Liste kann allerdings auch Wildcards enthalten:
#!/usr/bin/kshtypeset chLoopVar=""
# ---------------------------- Schleife mit Festwerten
for chLoopVar in a b c d e ; do
print - "Der Wert der Variablen chLoopVar ist: $chLoopVar"
done
# ---------------------------- Schleife mit Files
print - "Eine Liste von txt-Dateien:"
for chLoopVar in *txt ; do
print - " -> $chLoopVar"
done
exit 0
Die while- und die until-Schleife sind sowohl syntaktisch gleich wie auch logisch aquivalent, mit dem Unterschied, dass die until-Schleife ausgefuhrt wird, bis eine bestimmte Bedingung eintritt, die while-Schleife hingegen, solange eine bestimmte Bedingung erfullt ist. Die folgenden Ausfuhrungen zur while-Schleife gelten deshalb sinngemass auch fur die until-Schleife.
Die while-Schleife arbeitet etwas anders als von anderen Sprachen gewohnt, weil die KornShell ursprunglich keine eigene Methode fur Vergleiche kannte und sich deshalb des externen Kommandos test bediente. Mittlerweile hat die KornShell zwar eine eingebaute Funktion, die diesem Kommando entspricht, dennoch hat sich die Syntax der Schleife nicht geandert. while fuhrt den Schleifenkorper so lange aus, wie ein angegebenes Kommando den Error Level 0 (entspricht TRUE) zuruckgibt.
Liste von Kommandos
done
until Kommando ; do
Liste von Kommandos
done
Wie das folgende Beispiel zeigt, ersetzen in der KornShell while-Schleifen die in anderen Sprachen eingesetzten for-Schleifen. Das zweite Beispiel zeigt die Flexibilitat, die durch Einsatz des externen Kommandos gewonnen wird. Das shellinterne Kommando read wird in Verbindung mit einer Pipeline benutzt, einen Datenstrom zeilenweise zu verarbeiten:
typeset -i iLoopVar=0
typeset chLine=""
# ------------------------------- while-Schleife als for-Schleifen-Ersatz
while [ $iLoopVar -le 10 ] ; do
print - "Wert von iLoopVar: $iLoopVar"
(( iLoopVar += 1 )) # inkrementiere iLoopVar
done
# ------------------------------- listet alle Kommandos mit 3 Buchstaben in /usr/bin
find /usr/bin -name "???" -print | while read chLine ; do
print - "Kommando: $chLine"
done
exit 0
Die KornShell kennt zwei Arten der Verzweigung: if..fi und case..esac.
if verwendet wie auch while ein externes Programm, um den benotigten logischen Wert zu generieren. if kann optional mittels des Keywords elif auch mehrere Bedingungen verarbeiten, ebenfalls optional ist ein bei Nichtzutreffen aller vorheriger Bedingungen auszufuhrender else-Zweig.
Liste von Kommandos
elif Kommando ; then
Liste von Kommandos
elif Kommando ; then
Liste von Kommandos
...
else
Liste von Kommandos
fi
Bei ublichen Vergleichen wird dafur test bzw. dessen eingebautes Pendant benutzt, es kann aber auch ein beliebiges Programm ausgefuhrt und - abhangig von dessen Ruckgabewert - eine Aktion gestartet werden:
typeset -i iIn=0
# ------------------------------- einfaches if
if [ 1 -eq 1 ] ; then
print - "1 ist tatsachlich gleich 1"
fi
# ------------------------------- if-else
if /path/to/program -opt arg1 arg2 ; then
print - "Programm program wurde ohne Fehler beendet."
else
print - "Programm program lieferte einen Fehler zuruck."
fi
# ------------------------------- mehrstufiges if
print - "Geben Sie eine Ziffer (0-3) ein:" ; read iIn
if [ $iIn -eq 0 ] ; then
print - "Sie haben 0 eingegeben."
elif [ $iIn -eq 1 ] ; then
print - "Sie haben 1 eingegeben."
elif [ $iIn -eq 2 ] ; then
print - "Sie haben 2 eingegeben."
elif [ $iIn -eq 3 ] ; then
print - "Sie haben 3 eingegeben."
else
print - "Sie haben was anderes eingegeben."
fi
exit 0
case wertet einen einzelnen Ausdruck durch Variablenexpansion aus und fuhrt aus mehreren alternativen Codeblocken abhangig von dessen Wert (das kann eine Shell Regular Expression, auch bekannt als File Glob, sein) einen davon durch. Das entspricht annahernd dem aus Pascal bekannten case .. of bzw. dem switch() aus C.
Wert)
Kommando
...
;;
Wert)
Kommando
...
;;
...
esac
Das obige Beispiel, mit case anstatt if ausgefuhrt, wurde lauten:
typeset -i iIn=0
print - "Geben Sie eine Ziffer (0-3) ein:" ; read iIn
case $iIn in
0)
print - "Sie haben 0 eingegeben."
;;
[123]) # 1, 2 oder 3 als Regexp
print - "Sie haben 1, 2 oder 3 eingegeben."
;;
*) # default-Ast
print - "Sie haben etwas anderes eingegeben."
;;
esac
exit 0
Funktionen
[Bearbeiten | Quelltext bearbeiten]Wie in allen anderen prozeduralen Programmiersprachen gibt es auch in der KornShell die Moglichkeit, logisch in sich geschlossene und/oder oftmals wiederkehrende Codeteile in Subroutinen - hier Funktionen genannt - auszulagern. Die Syntax ist mit jener der Bourne-Shell bzw. der POSIX-Shell identisch, die KornShell versteht beide Varianten:
function Funktionsname # Bourne Shell-artig{
Kommando
Kommando
...
}
Funktionsname () # POSIX-Shell-artig
{
Kommando
Kommando
...
}
Zum Unterschied von anderen Programmiersprachen wird die Ein- bzw. Ausgabe allerdings regelmassig dazu verwendet, Eingaben von anderen Programmteilen zu empfangen bzw. Ergebnisse an andere Programmteile zu ubermitteln (Pipelining). In dieser Hinsicht verhalten sich Funktionen in der Shell ahnlich wie externe Programme.
Funktionsargumente werden - analog zu Kommandozeilenparametern - mittels positionaler Variablen ubergeben. Mit dem Keyword return (optional gefolgt von einem Integer mit Wert 0-255) kann der Rucksprung ins aufrufende Programm erfolgen und ein Funktionsergebnis, das von diesem als Error Level abgefragt und behandelt werden kann. Jede Funktion sollte deshalb mindestens ein solches return-Kommando (am Ende) enthalten.
function pShowText
{
print - "Dies ist ein Beispieltext."
print - "Bei Ausfuhrung der Funktion pShowText()"
print - "wird er auf
return 0
}
function pShowAnyText
{
typeset iCnt=0
while [ "$1" != "" ] ; do
print - "$1"
(( iCnt += 1 ))
shift
done
return $iCnt
}
# --------- Hauptprogramm
typeset iRetVal=0
print - "Hier wird pShowText() aufgerufen:"
pShowText
print - "das Ergebnis kann auch in einer Pipeline verarbeitet werden:"
pShowText | grep 'ei' # zeigt alle Zeilen, in denen "ei" vorkommt, also die ersten beiden
print - "pShowAnyText() gibt alle ubergebenen Argumente zeilenweise aus:"
pShowAnyText "erste Zeile" "zweite Zeile" "dritte Zeile"
iRetVal=$? # sichert den Ruckgabewert von pShowAnyText()
print - "Es wurden $iRetVal Argumente an pShowAnyText() ubergeben."
exit 0
Variablenexpansion oder Parameter Substitution
[Bearbeiten | Quelltext bearbeiten]Ein wesentlicher Unterschied zwischen Shell-Sprachen und herkommlichen Programmiersprachen ist die Behandlung von Variablen: in einer gewohnlichen Hochsprache ist eine Variable letztlich ein Speicherplatz, in dem ein Wert abgelegt sein und der mit einem Namen angesprochen werden kann. In der ksh (wie auch der bash und ahnlichen Sprachen) ist eine Variable zwar ebenfalls ein Platz zum Ablegen von Werten, aber als direkte Operation existiert nur die Zuweisung. Alle anderen Arten, die Variable anzusprechen, sind mehr oder minder komplexe Funktionen, die den Inhalt der Variablen als Argument bekommen, ihn bearbeiten und das Ergebnis dieser Bearbeitung ausgeben. Der Variableninhalt bleibt dabei selbst aber unverandert.
Die einfachste dieser Funktionen ist $, bzw. ${, welche den Inhalt der Variablen unverandert wiedergibt. Hingegen gibt etwa ${# die Lange der (String-)Variablen an und entspricht damit der C-Funktion strlen().
Der Interpreter wertet dabei in Kommandozeilen im Zuge des Command Line Parsing zuerst diese Variablenausdrucke aus und ersetzen sie durch ihr Ergebnis, bevor die so entstandene tatsachliche Kommandozeile auswertet wird. Die folgende Ubersicht zeigt einige Moglichkeiten, den Variableninhalt umzuformen:
${,} $- Inhalt der Variablen
ohne Anderung ${#} - Lange der Variablen
${:- } - Wenn die Variable
deklariert und ihr Inhalt ungleich Null (bzw. dem leeren String) ist, dann wird dieser Inhalt ausgegeben, ansonsten der im zweiten Teil des Ausdrucks angegebene. ${:= } - Wie
${, aber stattdessen wird der Variablen:- } der sich ergebende Wert zugewiesen. Es entspricht
="${ :- }"
- Dies wird ublicherweise verwendet, um Variablen mit Defaultwerten zu versorgen. Bei diesem wie auch allen ahnlichen Expansionen werden die dem Bezeichner folgenden Ausdrucke nur im Bedarfsfalle ausgewertet. Ungultige Ausdrucke konnen so fur langere Zeit unentdeckt bleiben, was eines der (durch entsprechende Tests zu vermeidenden) Risiken bei grosseren Shell-Skript-Projekten darstellt.
${,# } ${## } - Wenn die angegebene
mit dem Beginn des Inhalts der VariablenBezeichnerubereinstimmt, dann wird dieser Inhalt, vermindert um jenen Teil, der ubereinstimmt, ausgegeben, ansonsten der gesamte Inhalt. Auf diese Weise konnen Teile des Inhalts einer Variablen abgeschnitten werden. Bei der Variante mit#wird der kleinste ubereinstimmende Teil abgeschnitten, bei##der langste. Beispielsweise schneidet der Ausdruck${vom Pfadnamen alles bis zum letzten##*/} /ab, was etwa dem Kommandobasenameentspricht. ${,% } ${%% } - Ahnlich wie
${bzw.# } ${, nur dass der abzuschneidende Teil nicht vom Beginn, sondern vom Ende des Variableninhalts an verglichen wird. Das Kommando## } dirnamekann etwa durch die Expansion${emuliert werden.%/*}
typeset chVar="hello world"
print - "Inhalt der Variablen chVar: $chVar"
print - "Lange der Variablen chVar.: ${#chVar}"
print - "Defaultwert...............: ${chVar:-foo} hingegen: ${notdeclared:-foo}"
chVar="/path/to/some/file"
print - "Pattern entfernen..........: ${chVar##*/} bzw.: ${chVar%/*}"
exit 0
Literatur
[Bearbeiten | Quelltext bearbeiten]- Hans-Josef Heck: Standard-Betriebssystem UNIX fur Fortgeschrittene. Rowohlt, Hamburg 1991, ISBN 3-499-18187-8.
- Morris I. Bolsky, David A. Korn: The KornShell command and programming language. Prentice Hall, Englewood Cliffs, N.J. 1989, ISBN 0-13-516972-0.
- Morris I. Bolsky, David A. Korn: The new KornShell command and programming language. Prentice Hall PTR, Upper Saddle River, N.J. 1995, ISBN 0-13-182700-6.
- Barry Rosenberg: KornShell Programming Tutorial. Addison-Wesley Professional, Boston, M.A. 1991, ISBN 0-201-56324-X.
- Barry Rosenberg: Hands-On KornShell93 Programming. Addison-Wesley Professional, Boston, M.A. 1998, ISBN 0-201-31018-X.
Weblinks
[Bearbeiten | Quelltext bearbeiten]ksh(1): KornShell, a command and programming language - Debian GNU/Linux Ausfuhrbare Programme oder Shell-Befehle Handbuchseiteksh(1): public domain Korn shell - OpenBSD General Commands Manual- Webseite der Kornshell (anscheinend verwaist)
- pdksh-Webseite
- ksh
- Quelltexte der ksh93 (Paket ast-ksh)
- Offizielle Webseite der mksh (Weiterleitung auf aktuell funktionierende Version)
Einzelnachweise
[Bearbeiten | Quelltext bearbeiten]- | The Open Group Base Specifications; 2. Shell Command Language. Abgerufen am 23. Mai 2013 (englisch).
- | Website des KornShell-Projekts. Abgerufen am 19. Juni 2013 (englisch).
- | David Korn: KSH - A Shell Programming Language. USENIX Conference Proceedings, Toronto, Ont. Summer 1983, S. 191-202.
- | Sven Maschek: Some ksh versions available. 18. Februar 2012, abgerufen am 10. Februar 2016.
- | QNX Manual: sh. Abgerufen am 10. Februar 2016.
- | AIX v6.1 Infocenter. Abgerufen am 24. Mai 2013 (englisch).
- | Andreas Siegert: AIX Survival Guide. 1. Auflage. Addison-Wesley Professional, Boston 1996, ISBN 0-201-59388-2.
- | Package Notes and Changes (Changelog der ksh93). Archiviert vom Original (nicht mehr online verfugbar) am 31. Mai 2013; abgerufen am 23. Mai 2013 (englisch). Info: Der Archivlink wurde automatisch eingesetzt und noch nicht gepruft. Bitte prufe Original- und Archivlink gemass Anleitung und entferne dann diesen Hinweis.@1@2Vorlage:Webachiv/IABot/www2.research.att.com
- | aminet.net
- | David Korn Tells All (Question 5, "True Story?"). Abgerufen am 24. Mai 2013 (englisch).
- | David Korn Tells All (Question 1, "Comparison"). Abgerufen am 8. Juni 2013 (englisch).