<> ---- Dies ist eine kurze Referenz kleiner (b)ash-Wissensfetzen. Falls irgendwas nur mit der bash, aber nicht mit der ash laufen sollte, dann sollte dies explizit gekennzeichnet werden! = Allgemeines = == Eingaben/Ausgaben == >DATEI:: Standard-Ausgabe (1) in DATEI schreiben 1>DATEI:: dito >>DATEI:: Standard-Ausgabe (1) an DATEI anhängen 2>DATEI:: Fehler-Ausgabe (2) in DATEI schreiben 1>&2:: Standard-Ausgabe (1) zur Fehler-Ausgabe (2) umleiten 2>&1:: Fehler-Ausgabe (2) zur Standard-Ausgabe (1) umleiten &>DATEI:: Standard- und Fehlerausgabe in Datei schreiben DATEI:: DATEI mit dem Datei-Deskriptor Nummer `N` als nur-schreiben verknüpfen N<>DATEI:: DATEI fuer schreib/lese-Zugriffe als Nummer `N` öffnen N<< TRENNER:: der folgende Text bis zum Auftreten einer Zeile, in der nur TRENNER steht, wird als Eingabestrom verwendet{{{ echo <&1` lenkt die Fehlerausgabe auf die Standard-Ausgabe um) * `&-` als DATEI schließt den angegebenen Strom == Befehls-Verkettungen == ||:: ODER - führt das folgende Kommando nur aus, wenn das erste nicht mit Fehlercode `0` beendet wurde &&:: UND - nur, falls das erste Kommando erfolgreich war :: die Kommandos werden nacheinander ausgeführt &:: das Programm wird im Hintergrund ausgeführt { BEFEHLE; }:: führt die Befehle in der aktuellen Shell aus (Vorsicht - falls durch eine UND-/ODER-Verknüpfung die schließende Klammer übersprungen wird, führt das zu irritierenden Fehlermeldungen) (BEFEHLE):: führt die Befehle in einer neuen Shell aus (also werden keine Variablen der aktuellen Shell verändert usw.) == Anführungsstriche == doppelte:: Variablen und rückwärtige Anführungsstriche (Backticks) werden aufgelöst einfache:: beides wird nicht aufgeloest rückwärtige:: der Text wird als Kommando interpretiert und liefert dessen Ausgabe zurück = Strukturen = * while- und for-Schleifen können durch "break" beendet und durch "continue" mit der nächsten Iteration fortgesetzt werden * BEDINGUNG ist üblicherweise ein Programm, dessen Exit-Code verwendet wird * falls dazu das builtin "test" verwendet wird, ist auch die verkürzte Schreibweise: "`[ TEST_PARAMETER ]`" möglich (die Leerzeichen zwischen den eckigen Klammern sind wichtig!) * BEDINGUNG kann auch eine beliebig lange Liste von Kommandos sein - relevant ist nur der Exit-Code des letzten Befehls * anstelle der Zeilenumbr+che kannst du natürlich auch ein Semikolon verwenden == while == {{{while BEDINGUNG do BEFEHL BEFEHL done}}} * `BEDINGUNG` ist dabei irgendein Programm, das entweder den Exit-Code `0` (=wahr) oder eine einen beliebigen anderen Exit-Code (=falsch) zurückliefert - häufig ist dies das Programm `test` == until == siehe "while" - einfach "until" stattdessen einsetzen == for == {{{for VAR in LISTE do BEFEHL BEFEHL done}}} * VAR ist der Name (ohne "$") der Variablen, die das aktuelle Element aus LISTE enthaelt * dabei solltest du LISTE nicht in Anfuehrungsstriche setzen, damit die einzelnen Parameter nicht als Ganzes interpretiert werden == if == {{{if BEDINGUNG then BEFEHL BEFEHL else BEFEHL BEFEHL fi}}} == case == {{{case $VARIABLE in a|b ) BEFEHL BEFEHL ;; c ) BEFEHL ;; * ) BEFEHL ;; esac}}} = String-Funktionen (Variablen-Substitution) = == in Abhängigkeit vom Status der Variablen == ${var}:: die Variable ${var:-default}:: falls die Variable nicht gesetzt ist, wird der default-Wert zurückgegeben ${var:=default}:: falls die Variable nicht gesetzt ist, wird ihr der default-Wert zugewiesen ${var:?[meldung]}: falls die Variable nicht gesetzt ist, wird `meldung` (oder ein Standard-Text) an Standard-Error ausgegeben und das Skript mit Fehlercode beendet - ansonsten wird der Variablenwert zurückgegeben ${var:+alternative}:: falls die Variable gesetzt ist, wird `alternative` zurückgegeben, ansonsten der Wert der Variable (also null (leer)) Anmerkung zu den vorherigen Beschreibungen: * "nicht gesetzt" bedeutet eigentlich "nicht gesetzt oder null" * falls wirklich nur "nicht gesetzt" gemeint ist, dann muss der Doppelpunkt weggelassen werden == zeichenorientiert == ${#var}:: die Anzahl der Zeichen in `var` ${var:offset}:: einen Teilstring von `var`, beginnend beim Zeichen Nr. `offset` ${var:offset:length}:: liefert `length` Zeichen von `var` beginnend bei Zeichen Nr. `offset` == Ersetzungen == ${var%regexp}:: entfernt das kleinstmögliche Suffix, für das `regexp` zutrifft (aus `var=gurgelFressFisch` und `regexp=F.*$` wird somit `gurgelFress` ${var%%regexp}:: entfernt das größtmögliche Suffix, fuer das "regexp" zutrifft (das obige Beispiel ergibt dann "gurgel") ${var#regexp}:: entfernt das kleinstmögliche Präfix ${var##regexp}:: entfernt das größtmögliche Präfix * Erklärung: `entfernt` bedeutete in den vorangegangenen Beispielen nicht, dass die Variable verändert wird, sondern, dass dieser Teil des Strings nicht zurückgeliefert wird === gebräuchliche Beispiele === ${DATEINAME%.pdf}:: liefert den Inhalt von `DATEINAME` ohne die Endung `.pdf` (nur zur Perfektion: da ein Punkt in einem regulären Ausdruck als beliebiges Zeichen interpretiert wird, würde beispielsweise auch die Endung `zpdf` entfernt werden - korrekt wäre also: `${DATEINAME%\.pdf}`) = Berechnungen = mit {{{$((formel))}}} koennen einfache arithmetische Operationen ausgefuehrt werden * alle Variablen in der Berechnung müssen mit dem ueblichen Dollarzeichen markiert werden (fuer ash erforderlich - fuer bash nicht) * Vorsicht: {{{i=$(($i+1))}}} und {{{i=$((i+1))}}} ist fuer die bash nicht dasselbe - ersteres wird als unendliche Rekursion abgelehnt und letzteres liefert das erwartete Resultat (bei der ash funktioniert nur die erste Variante) * Update: dies gilt anscheinend nur bis Bash v3.x - ab v4.0 funktioniert auch {{{i=$(($i+1))}}} = wichtige Shell-Variablen = $1 .. $9:: die Parameter beim Skript-Aufruf (koennen mit "shift" weitergeschoben werden, um an die folgenden Parameter zu gelangen) $0:: der Name des Shell-Skripts $*:: alle Parameter der Shell $@:: so aehnlich, wie "$*" $#:: die Anzahl der Parameter $?:: Exit-Code der letzten Pipeline bzw. des letzten (Vordergrund-)Kommandos $!:: Exit-Code der letzten Pipeline bzw. des letzten (Hintergrund-)Kommandos $$:: die `pid` (Prozessnummer) des Skripts = wichtige builtins = . DATEI:: liest DATEI ein und führt deren Zeilen in der aktuellen Shell aus (wichtig, um die Variablen der aktuellen Shell beeinflussen zu können) eval STRING:: wertet STRING aus und führt die resultierende Zeichenkette aus read [-p TEXT] VAR:: gibt eventuell `TEXT` aus und wartet auf eine Eingabezeile von Standard-Input - diese wird VAR zugewiesen (es können auch mehrere Variablennamen angegeben werden - diese enthalten dann die einzelnen (durch Leerzeichen oder Tabulatoren getrennten) Teile der Eingabe; in der letzten Variablen steht immer der verbleibende Rest der Eingabe) - der Eingabestrom kommt oft aus einer Datei: `read` liefert dann einen Fehlercode zurück, wenn das Dateiende erreicht wird set:: Shell-Optionen setzen -x:: jede Skript-Zeile (nach Variablenexpansion usw.) ausgeben, bevor sie ausgeführt wird -u:: falls eine verwendete Variable nicht gesetzt ist, dann beende das Skript mit Fehler (schützt vor Tipp-Fehlern) -e:: Skript sofort abbrechen, falls ein Kommando mit Fehler beendet wurde (gilt nicht fuer `test`, `if`, `||`-Verkettungen usw.) shift [n]:: rückt die aktuellen Parameter (`$1` usw.) um `n` weiter test:: RTFM trap AKTION SIGNALE:: führt `AKTION` (in einfachen Anführungsstrichen) aus, wenn das Programm eins der angegebenen Signale empfängt; die Signale können als Zahlen oder per Name angesprochen werden; "0" bedeutet Skript-Ende exit [X]:: beendet das Skript und gibt den Exit-Code `X` (bzw. 0) zurück = Funktionen = {{{ name () BEFEHL}}} oder {{{ name () { BEFEHL BEFEHL } }}} * `return X` liefert den Exit-Code `X` zurück * die Parameter der Funktion sind als "$1" bis "$9" verfuegbar * der Aufruf einer Funktion startet einen eigenen Prozess * Variablen, die nur innerhalb der Funktion gültig sein sollen, müssen bei der ersten Verwendung durch ein vorangestelltestes `local` markiert werden * der Aufruf einer Funktion erfolgt einfach durch ihren Namen = Unterschiede von ash/bash = * die mathematische Auswertung erfordert bei der ash die übliche Variablenmarkierung mit dem "$" (innerhalb der doppelten Klammern), während die bash dies nicht verlangt - allerdings wendet die bash bei Anwesenheit des "$" eine komplexere Logik an, auf dass "i=$(($i+1))" wegen unendlicher Rekursion abgelehnt wird = Bock auf mehr? = Dann geh zu: * http://freshmeat.net/projects/advancedbashscriptingguide/?branch_id=130&release_id=159084