test (Unix)
test (/bin/test) ist ein Unix-Werkzeug, mit dem logische Vergleiche angestellt werden können. Es gehört zur grundlegenden Ausstattung Unix-artiger Systeme und sein Verhalten ist durch den POSIX-Standard genormt.[1]
Viele Shells implementieren es mittlerweile als „built-in“-Kommando, aber diese Implementierungen leiten sich alle von der ursprünglichen Version als stand-alone-Programm ab.
Aus Usability-Gründen existiert das Programm auch unter dem Namen /bin/[, das sich genau wie /bin/test verhält, nur dass es als letztes Argument ] erwartet. Siehe Geschichte.
Arbeitsweise
Konventionsgemäß werden von Unix-Programmen Werte von 0 als logisch wahr, Werte ungleich 0 als unwahr bzw. falsch interpretiert. test analysiert den in den übergebenen Argumenten beschriebenen einfachen oder zusammengesetzten logischen Ausdruck und weist das Ergebnis desselben als Rückgabewert (Return-Code, RC) 0 oder 1 aus. Da die Verzweigungsoperationen der Shell-Skriptsprachen typischerweise vom Rückgabewert abhängen, ist damit eine generalisierte Methode, Verzweigungen zu parametrieren, geschaffen.
Im folgenden Anwendungsbeispiel wird die do..while-Schleife solange durchlaufen, wie der Wert Counter kleiner als oder gleich 100 ist:
#!/bin/ksh typeset Counter=0 while test $Counter -le 100 ; do (( Counter += 1 )) done
Parameter
/bin/test nimmt als Argumente einerseits Werte (Strings, Integers und Dateinamen), andererseits logische Operatoren (Vergleiche, Existenzbedingungen von Datei-Metadaten und logische Verknüpfungen) entgegen. Daraus wird der Wahrheitswert einer einfachen oder zusammengesetzten logischen Funktion ermittelt. Die Operatoren gliedern sich in:
Dateibezogene Operatoren
Datei-Operatoren erwarten einen einzelnen Pfadnamen als Argument. Es kann die Existenz einer Datei (-e <file> = die Datei existiert), das Bestehen bestimmter Zugriffsrechte (-r <file> = die Datei existiert und ist lesbar) oder auf einen bestimmten Dateityp (-d <file> = die Datei existiert und ist ein Directory) geprüft werden.
Integer-Operatoren
Integer-Operatoren erwarten zwei Integer-Werte als Argumente, die gemäß dem Operator miteinander verglichen werden (<Int1> -ge <Int2> = Int1 ist größer oder gleich Int2). Dies entspricht den Vergleichsoperatoren >, >=, >==, etc. der meisten Programmiersprachen. Da die Shells gewöhnlich nicht zwischen Datentypen unterscheiden, muss das aufrufende Programm (meist ein Script) selbst Sorge dafür tragen, dass die übergebenen Werte auch als Integer interpretierbar sind. Argumente, die keine Integer sind, führen zu einem Laufzeitfehler.
String-Operatoren
String-Operatoren erwarten zwei Strings als Argumente und prüfen auf Gleichheit oder Ungleichheit ("<String1>" = "<String2>" = String1 ist identisch mit String2). Wegen der oben erwähnten mangelnden Typgenauigkeit der Shell-Sprachen können zwar Integer-Werte als Strings aber nicht umgekehrt miteinander verglichen werden. Die aus anderen Programmiersprachen gewohnte Mehrdeutigkeit von Vergleichsoperatoren, dass also etwa der Vergleichsoperator == sowohl die Gleichheit von Strings wie von numerischen Werten feststellt, ist ausdrücklich nicht gegeben.
Logische Operatoren
Mehrere der oben genannten Einzelbedingungen können darüber hinaus noch durch logisches UND bzw. ODER miteinander verknüpft werden (<Int1> -ne <Int2> -a -r <file> = <Int1> ist nicht gleich <Int2> UND der ausführende Prozeß hat Leserechte auf <file>). Allerdings schränkt der POSIX-Standard das Verhalten von test als "unspecified" bei der Übergabe von mehr als 4 Argumenten ein.[1]
Operator-Präzedenz, Gruppierung
Es gilt implizit die auch in anderen Programmiersprachen übliche Präzedenz logischer Operatoren, aber auch ein davon abweichendes Verhalten kann mit Hilfe von Gruppierungssymbolen (\(...\)) erzwungen werden. Dies hat zwar durch die Limitierungen des POSIX-Standards kaum eine Bedeutung, aber die allermeisten realen Implementierungen können deutlich mehr (und für praktische Zwecke eine unbegrenzte Anzahl) an Argumenten als die spezifizierten 4 verarbeiten:
#! /bin/ksh typeset -i x=0 typeset -i y=1 typeset z="" if test \( $x -gt 0 -a $y -ne 0 \) -o "$z" != "" ; then print - "( falsch UND wahr ) ODER wahr -> wahr" fi if test $x -gt 0 -a \( $y -ne 0 -o "$z" != "" \) ; then : else print - "falsch UND ( wahr ODER falsch ) -> falsch" fi
Geschichte
Der ursprüngliche Entwurf sah test vor, wie es heute existiert. Da sich aber damit das Erscheinungsbild von Shell-Programmen deutlich von dem anderer Programmiersprachen unterschied, wurde test mit einem Link auch als [ verfügbar gemacht. Das änderte das Erscheinungsbild von Scripten zu:
#!/bin/ksh typeset Counter=0 while [ $Counter -le 100 ; do (( Counter += 1 )) done
hätte aber zu dem etwas ungewöhnlichen Umstand geführt, dass scheinbar eine geöffnete Klammer nicht geschlossen wird. Deshalb wurde das Binary dahingehend verändert, ein abschließendes "]" als Argument zu erwarten, wenn es als [ aufgerufen wird. Damit war das heute übliche Erscheinungsbild in Scriptsprachen festgelegt. Das ist auch der Grund dafür, warum [ und ] stets von Leerzeichen (dem Internal Field Separator der Shell) umschlossen sein müssen:
#!/bin/ksh typeset Counter=0 while [ $Counter -le 100 ] ; do (( Counter += 1 )) done
Viele heutige Betriebssystemversionen ersetzen den ursprünglichen Link durch ein eigenes Binary, was allerdings keinen Einfluss auf die Funktion hat. Viele der heute üblichen Unix-Shells haben aus Performance-Gründen ein identisch funktionierendes Built-in, sodass für einen Vergleich kein externes Programm aufgerufen zu werden braucht. Beispielsweise verwenden die Korn Shell und die Bourne-again shell [[, das folgerichtig ]] als abschließendes Argument erwartet:
#!/bin/ksh typeset Counter=0 while [[ $Counter -le 100 ]] ; do (( Counter += 1 )) done
Weblinks
test
: evaluate expression – Open Group Base Specificationtest(1)
: condition evaluation utility – OpenBSD General Commands Manualtest(1)
: Dateitypen überprüfen und Werte vergleichen – Debian GNU/Linux Ausführbare Programme oder Shell-Befehle Handbuchseite
Einzelnachweise
- ↑ a b test-Spezifikation der Open Group. Abgerufen am 13. April 2013 (englisch).