Sprache Sh
 
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern

Unix Shell Programmierung mit sh kompatiblen Shells

In vielen Fällen lässt es sich unter Unix vermeiden ein spezielles compiliertes Program zu schreiben, weil durch Aufrufen einzelner anderer Programme und die Bearbeitung der Ausgaben und Eingaben dieser einfacher die Funktionalität dargestellt werden kann. Die Programme die Eingaben an der Tastatur entgegen nehmen, diese entsprechend interpretieren und ein anderes Program ausführen sind weithin als Shells bekannt. Moderne Shells bieten viele Möglichkeiten mit ihnen auch richtige Programme zu erstellen.

Hier werden einige grundlegende Konzepte der Programmierung in der POSIX normierten sh vorgestellt.

Inhaltsverzeichnis dieser Seite
Unix Shell Programmierung mit sh kompatiblen Shells   
Allgemeines   
Variablen   
"Normale" Variablen   
Environment Variablen   
Expandieren von Variablen   
Wildcards   
Interpretation einfacher Kommandos   
Ein-/ Ausgabe   
Kommandos verknüpfen   
Beispiel   
Kommando Ersetzung (Command Substitution)   
Konditionale   
Schleifen   
Kommandozeilenparameter   
Spezialitäten   
PitFalls?   
FeedBack   

Allgemeines    

Im allgemeinen ist es egal, ob man Kommandos einzeln auf der Kommandozeile eingibt oder in einer Datei zur wiederholten Abarbeitung ablegt.

Das aktuelle Verzeichnis (working directory) ist immer jenes, in dem das Skript aufgerufen wird. Natürlich ist es auch möglich das nachträglich mit 'cd' zu wechseln.

Variablen    

"Normale" Variablen    

Durch ein einfaches
variablenname=Wert
wird die eine Variable erzeugt und belegt.

Environment Variablen    

Das Environment eines Prozesses sind externe Variablenbelegungen, die einem Programm beim Start mitgegeben werden, von diesem modifiziert werden und an seine Kindprozesse weitergegeben wird.

In der sh kann eine Variable durch
export variablenname
in das Environment aufgenommen werden. Damit werden meist Defaultwerte oder userspezifische Einstellungen für Programme gesetzt.

Expandieren von Variablen    

Variablen werden mit
$variablenname
angesprochen.

Wildcards    

Die einfachen "Glob" Wildcards in POSIX kennen folgende Elemente:

/FragenWC

Interpretation einfacher Kommandos    

Nach der Bestätigung des Befehls auf der Kommandozeile wird dieser einmal an Spaces und TABs zerlegt. Variablen und andere Spezialitäten werden expandiert. Dann wird das Kommando exekutiert.

Will man spezielle Zeichen der sh (Globs, Leerzeichen oder ähnliches) "escapen" (also unschädlich machen) kann man für einzelne Vorkommen den "\" benutzen. Für längere Abschnitte kann man einfache oder doppelte Anführungszeichen benutzen. Dabei unterdrücken einfache Anführungszeichen die Variablenerweiterung, doppelte nicht.

Ein-/ Ausgabe    

Ein Prozess hat drei Standard Filedeskriptoren:

NummerName
0Standard Input (stdin)
1Standard Output (stdout)
2Standard Error (stderr)

Durch Anhängen spezieller Konstrukte können diese Deskriptoren in verschieden Arten verdreht werden:

SyntaxAuswirkung
< filenamedas Kommando liest von filename
> filenamestdout wird nach filename umgeleitet; die Datei wird dabei überschrieben
>> filenamewie "> filename" allerdings wird angehängt und nicht überschrieben
2>&1stderr auf stdout legen; zB für folgendes
> filename 2>&1stdout und stderr nach filename (dabei ist die Reihenfolge wichtig)
command1 | command2stdout vom ersten Kommando wird an den stdin des zweiten weitergeleitet

Dabei werden i.A. tatsächlich auf OS-Ebene die Filedeskriptoren (SprachPolizei?) verknüpft, sodaß direkte Kommunikation stattfindet.

Kommandos verknüpfen    

Kommandos können zu sogenannten Listen verknüpft werden. Dabei wird der Exit-Status der Programme als boolsche Werte interpretiert: 0 ist TRUE und ungleich 0 ist FALSE. Wie aus anderen Sprachen gewohnt werden "&&" und "||" mit Shortcutting (SprachPolizei) evaluiert.

Der Strichpunkt (";") ist ein einfacher Statement Seperator mit niedrigerem Vorrang ("precedence") als "&&" und "||".

Einfache runde Klammern starten die geklammerte Liste in einem eigenen Prozess (sog. Subshell) und können daher zur Vorrangbestimmung eingesetzt werden.

Beispiel    

Das Programm prog ausführen und bei erfolgreicher Beendigung "OK" sonst "FAIL" ausgeben.
  ''prog'' && echo OK || echo FAIL

  (''prog'' && echo OK) || echo FAIL

  '''Warum nicht:''' ''prog'' || echo FAIL && echo OK '''?'''

Jene die einen Tip brauchen, dürfen in den /Lösungen nachschauen.

Kommando Ersetzung (Command Substitution)    

Um den Output einer Liste weiterzuverwenden kann man diesen mit [Code]`liste`] in die Kommandozeile einbauen.

echo "`cat ''filename''`"

Konditionale    

if list; then list; [ elif list; then list; ] ... [ else list; ] fi

Schleifen    

for variablenname in wortliste ; do list; done

Die list wird für jedes wort aus der wortliste mit variablenname=wort ausgeführt.

while bedingungs_list; do body_list; done

Solange der Exit-Status von bedingungs_list null ist, wird body_list wiederholt.

Kommandozeilenparameter    

Werden der sh Argumente auf der Kommandozeile übergeben, so kann man diese in verschiedener Art verwenden.

Beispiel:

  shellskript arg1 arg2

Direkte Adressierung:

  echo $0
  echo $1
  echo $2

liefert

  shellskript
  arg1
  arg2

Indirekte Addressierung:

  echo $1
  shift
  echo $1

liefert

  arg1
  arg2

Mit einer Schleife kann dabei die gesamte Kommandozeile abgearbeitet werden.

Spezialitäten    

Will man die gesamte (verbleibende) Kommandozeile unverändert weiterreichen so benutzt man am besten
"$@"
. Dadurch wird sichergestellt, daß keine weiteren Veränderungen durch die sh durchgeführt werden. Will man ausnahmsweise den String nochmals durch die sh parsen lassen so kann man
$*
benutzen.

Zur Demonstration des Unterschiedes nehmen wir ein File mit dem Namen "space space" und eines mit dem Namen "space" im aktuellen Verzeichnis an und schreiben dieses Skript:

#!/bin/sh

# Parameter ausgeben
echo '$1:'"'$1'" '$2:'"'$2'"

# Erster Test
echo 'ls -l "$@"'
ls -l "$@"

# Zweiter Test
echo 'ls -l $*'
ls -l $*

Probieren wir das einmal aus:

david@diode:~/tmp$ ./test.sh 'space space' space
$1:'space space' $2:'space'
ls -l "$@"
-rw-r--r--    1 david    david           0 May 16 00:02 space
-rw-r--r--    1 david    david           0 May 16 00:02 space space
ls -l $*
-rw-r--r--    1 david    david           0 May 16 00:02 space
-rw-r--r--    1 david    david           0 May 16 00:02 space
-rw-r--r--    1 david    david           0 May 16 00:02 space
david@diode:~/tmp$ 

Wie man sieht konnte beim ersten Mal das Leerzeichen gerettet werden. Beim zweiten Mal hat die sh zugeschlagen und die Kommandozeile erneut geparst, weshalb nicht ls -l 'space space' space sondern ls -l space space space ausgeführt wurde.

PitFalls?    

Da sh-kompatible Shells WhiteSpace zum tokenizen benutzen, sind folgende Befehle nicht gleichwertig

  variable=wert
  variable= wert
  variable = wert

und werden so interpretiert:

  variable=wert
  variable='' commando
  commando argument1 argument2

FeedBack    

Wollt ihr mehr oder lest ihr Euch eh brav die man-page durch? ;-))

Beides. Wir wollen mehr und lesen brav. :-)


Siehe auch SkriptSprache SpracheShell KommandozeilenInterpreter
KategorieProgrammierSprache KategorieProgrammierBeispiele
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Text dieser Seite ändern (zuletzt geändert: 3. Mai 2003 20:20 (diff))
Suchbegriff: gesucht wird
im Titel
im Text