Bash Programmierung: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
 
(80 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
=Bash Basics=
+
=Allgemeines=
*[[Einfache Shellsonderzeichen]]
+
*[[Thomas Will]]
*[[Bash Eingabe/Ausgabe]]
+
*[[Zeiten]]
*[[Jokerzeichen]]
+
=Themen=
*[[Prinzip der Bash]]
+
*[[Bash Programmierung Inhalt]]
=Die Ausgabe des Shellskriptes=
+
<!-- == Tag 1 == -->
*./skript
+
* [[Die Geschichte der Shells]]
Mon Dec 15 09:07:22 CET 2003
+
* [[Ziele des IT Trainings Bash Programmierung]]
dozent
+
* [[Arten von Shells]]
/home/thomas/bin
+
* [[Prinzip der Bash]]
 +
* [[Unterschiede zwischen bash und powershell]]
 +
* [[Skript Interpreten in Linux]]
 +
* [[Möglichkeiten ein Shellskript aufzurufen]]
 +
* [[Bash Eingabe/Ausgabe]]
 +
* [[Bash Pipe]]
 +
* [[Einfache Shellsonderzeichen]]
 +
* [[Jokerzeichen/Wildcard]]
 +
* [[Ein paar Kommandos]]
 +
* [[Kommandolokalisierung]]
 +
* [[Bash ssh in Programmen nutzen]]
 +
<!-- == Tag 2 == -->
 +
* [[Ablauf eines Shell-Skriptes]]
 +
* [[Bash Variablen]]
 +
* [[Bash Dateien]]
 +
* [[Here Dokument]]
 +
* [[Here String]]
 +
* [[read-Kommando]]
 +
* [[Endestatus]]
 +
* [[Bash Einfache Verzweigungen]]
 +
* [[test-Kommando]]
 +
* [[Bash Das neue Test Kommando]]
 +
* [[Rechnen mit der Bash]]
 +
<!-- == Tag 3 == -->
 +
<!-- == Tag 4 == -->
 +
* [[Bash Der if-Block]]
 +
* [[Bash Der case-Block]]
 +
* [[Bash Die while-Schleife]]
 +
* [[Bash Die until-Schleife]]
 +
* [[Bash Die for-Schleife]]
 +
* [[Bash Steuerung der Ablaufanweisungen]]
 +
* [[Bash funktion]]
 +
* [[cron]]
 +
* [[Bash Signalverarbeitung]]
 +
<!-- == Tag 5 == -->
 +
* [[Bash printf]]
 +
* [[Aliase]]
 +
* [[Prozesse]]
 +
* [[Bash Filedeskriptoren]]
 +
* [[Bash Farben]]
 +
* [[Bash getopts]]
 +
* [[Bash eval]]
 +
* [[Optionen der Bash]]
 +
* [[Bit Operationen mit der Bash]]
 +
* [[Bash Skripte]]
 +
* [[Mail Kommando]]
 +
* [[Bash Passwort generieren]]
 +
* [[Bash Alter eine Datei]]
 +
* [[Ssh VPN]]
 +
* [[Aufgaben gesamt]]
  
=Struktogramm nach Nassi-Shneiderman=
+
= Links=
 
+
* http://openbook.rheinwerk-verlag.de/shell_programmierung/
{| border=1 cellpadding="2"
+
* http://mywiki.wooledge.org/BashFAQ/031
|-
+
* http://tldp.org/LDP/abs/html/index.html
| Ausgabe Datum
+
* http://openbook.rheinwerk-verlag.de/shell_programmierung/shell_006_003.htm
|-
+
* https://kuepper.userweb.mwn.de/informatik/printf.pdf
| Ausgabe Rechnername
 
|-
 
| Ausgabe Arbeitszverzeichnis
 
|}
 
 
 
*[[Interpretator]]
 
 
 
==Ablauf eines Shell-Skriptes==
 
*Starten einer Subshell
 
*Lesen der Skriptdatei von der Subshell (zeilenweise)
 
*Kommandos werden nacheinander abgearbeitet
 
 
 
Beenden der Subshell und Rückkehr zur aufrufenden Shell
 
 
 
==Möglichkeiten ein Shellskript aufzurufen==
 
===bash skript (r)===
 
* Starten einer Subshell
 
* Lesen der Skriptdatei von der Subshell
 
* Kommandos werden nacheinander abgearbeitet
 
* Beenden der Subshell und Rückkehr zur aufrufenden Shell
 
''(Die Shell, die das Skript abarbeitet, kennt den Namen des Shellskriptes)''
 
 
===bash < skript (r)===
 
* Starten einer Subshell
 
* Lesen der Skriptdatei von der Subshell
 
* Kommandos werden nacheinander abgearbeitet
 
* Beenden der Subshell und Rückkehr zur aufrufenden Shell
 
''(Die Shell, die das Skript abarbeitet, kennt den Namen des Shellskriptes nicht)''
 
 
 
===./skript (rx)===
 
* Starten einer Subshell
 
* Lesen der Skriptdatei von der Subshell
 
* Kommandos werden nacheinander abgearbeitet
 
* Beenden der Subshell und Rückkehr zur aufrufenden Shell
 
''(Die Shell, die das Skript abarbeitet, kennt den Namen des Shellskriptes, es muss zusätzlich das Ausführungsrecht gesetzt sein.)''
 
 
 
===exec ./skript (rx)===
 
* Die Subshell ersetzt die aktuelle Shell (überlädt die aktuelle Shell)
 
* Lesen der Skriptdatei von der Subshell
 
* Kommandos werden nacheinander abgearbeitet
 
* Beenden der Subshell; danach ist der Prozess der aufrufenden Shell beendet.
 
 
 
===source skript  oder . skript (r)===
 
* Lesen der Skriptdatei von der aktuellen Shell
 
* Der interaktive Modus der aktuellen Shell wird „unterbrochen“
 
* Kommandos werden nacheinander abgearbeitet
 
''(Es wird kein neuer Prozess gestartet; Variablen haben in dieser Shell Gültigkeit)''
 
 
 
=Variablen=
 
==Skalare Variablen==
 
Eine Variable stellt einen Platzhalter dar. Man spricht von Variablensubstitution, wenn anstatt der
 
Variablen deren Wert bzw. Inhalt ausgegeben wird.Eine Variable muss im Gegensatz zu Programmiersprachen,
 
die kompiliert werden, nicht deklariert werden, da der Interpretor zu Laufzeit den Speicherplatz allokiert
 
(Belegung des Speicherplatzes zur Laufzeit).
 
 
 
Die Definition einer Variablen erfolgt durch die Nennung, gefolgt von einem = Zeichen, gefolgt von dem
 
Inhalt, der zugewiesen wird. Wichtig : zwischen der Variablen, dem = und dem Wert darf kein Leerzeichen
 
stehen. Man benutzt häufig Grossbuchtstaben, es sollten keine – benutzt  werden. 
 
 
 
Definition der Variable
 
*GLAS=bier
 
Ausgabe des Variableninhalts
 
*echo $GLAS
 
bier
 
Definition der Variable: 
 
*UNIXSYSTEM=/usr
 
:Variablensubstititution:
 
*ls -ld  $UNIXSYSTEM
 
drwxr-xr-x 11 root root 4096 2008-10-29 23:58 /usr
 
==Feld Variablen==
 
Definition der Feld Variablen
 
*farbe=(blau gelb gruen rot)
 
Ausgabe des Inhalts der Feld Variablen
 
*echo ${farbe[0]}
 
blau
 
*echo ${farbe[1]}
 
gelb
 
*echo ${farbe[2]}
 
gruen
 
*echo ${farbe[3]}
 
rot
 
==Der Exportbefehl==
 
Die Variable wird nicht automatisch an Kindprozess weitergegeben. Mit export wird eine Variable markiert,
 
sodass sie in die Prozessumgebung übernommen wird um beim Forken auch dem Kindprozess zur Verfügung zu stehen.
 
Alle exportierten Variablen können mit dem Befehl ''printenv'' oder ''env'' angezeigt werden. Wirklich alle
 
Shellvariablen werden mit set angezeigt.
 
 
 
==Kommandosubstitution==
 
Bei der Kommandosubstitution wird ein Kommando mit seinem Rückgabewert ersetzt.
 
Es existieren zwei Varianten
 
 
 
$(date)
 
 
 
`date`
 
 
 
Bei der ersten Variante besteht die Möglichkeit zu schachteln:
 
 
 
*cd $(echo /home/$(whoami))
 
*cd `echo /home/`whoami``
 
 
 
*date -u "+%X"
 
09:29:41
 
*MOMENT=$(date -u "+%X")
 
*echo $MOMENT
 
09:29:58
 
*echo $MOMENT
 
09:29:58
 
 
 
==Abgrenzen von Variablen==
 
Folgt einem Dollarzeichen $ ein Variablenname oder eine öffnende geschweifte Klammer ${...}, so spricht man
 
von einer Variablen- bzw. Parameterexpansion. Die geschweiften  Klammern dienen zur Gruppierung und sind bei
 
skalaren Variablen, die nicht per Parameterexpansion behandelt werden sollen, nicht notwendig.
 
 
 
*SUX=eins
 
*TUX=zwei
 
*SUXTUX=drei
 
 
*echo $SUX
 
eins
 
*echo ${SUX}
 
eins
 
*echo $SUXTUX
 
drei
 
*echo ${SUX}TUX
 
einsTUX
 
*echo ${SUX}${TUX}
 
einszwei
 
 
 
==Weitere Mechanismen zur Parameterexpansion==
 
Die weiteren Mechanismen zur Parameterexpansion manipulieren den Inhalt von Variablen.  "FARBE" bezeichnet
 
nachfolgend den Variablennamen und "rot" steht entweder für eine Zeichenkette oder für eine Variable, die
 
selbst wieder eine Parameter-, Kommando, Tildeexpansion oder eine arithmetische Berechnung beinhalten kann.
 
* ${FARBE:-rot}
 
Wenn die Variable $FARBE definiert ist, wird der Inhalt zurückgeliefert; wenn sie nicht definiert ist, wird
 
rot zurückgeliefert
 
*unset FARBE
 
*echo ${FARBE:-rot}
 
rot
 
*FARBE=gruen
 
*echo ${FARBE:-rot}
 
gruen
 
*echo $FARBE
 
gruen
 
*${FARBE:=rot}
 
 
 
Wenn die Variable $FARBE definiert ist, wird der Inhalt zurückgeliefert, wenn sie nicht definiert ist, wird
 
rot  zurückgeliefert und die Variable $FARBE wird mit dem Wert rot belegt (somit ist sie definiert).
 
 
 
*unset FARBE
 
*echo ${FARBE:=rot}
 
rot
 
*echo $FARBE
 
rot
 
 
 
* ${FARBE:?keine farbe gesetzt}
 
 
 
Wenn die Variable $FARBE definiert ist, wird der Inhalt zurückgeliefert, wenn sie nicht definiert ist, wird
 
'keine farbe' als Fehlermitteilung ausgegeben. Der Rückgabewert ist dann auch ungleich 0.
 
*unset FARBE
 
*echo ${FARBE:?keine farbe}
 
bash: FARBE: keine farbe
 
*echo $?
 
1
 
*FARBE=silber
 
*echo ${FARBE:?keine farbe}
 
silber
 
 
* ${FARBE:+rot}
 
 
 
Wenn die Variable $FARBE definiert ist, wird rot  zurückgeliefert, ansonsten nichts. 
 
*unset FARBE
 
*echo ${FARBE:+rot}
 
 
*FARBE=gelb
 
*echo ${FARBE:+rot}
 
rot
 
*echo $FARBE
 
gelb
 
 
* ${FARBE:4}
 
 
 
Der Inhalt der Variable wird ab der 4 Position bis zum Ende ausgegeben.
 
Es wird ab 0 gezählt.
 
 
 
*FARBE=rotweis
 
*echo ${FARBE:3}
 
weis
 
 
* ${FARBE:5:3}
 
 
 
Ab der 5 Position werden 3 Zeichen ausgegeben. Es wird ab 0 gezählt.
 
 
 
*FARBE=schwarzbraun
 
*echo ${FARBE:5:3}
 
rzb
 
 
 
* ${#FARBE}
 
Die Anzahl Zeichen der Variable wird ausgegeben
 
 
 
*FARBE=schwarzbraun
 
*echo ${#FARBE}
 
12
 
 
 
* ${FARBE#rot}
 
 
 
Wenn das Wort rot am Anfang der Variable steht wird der Rest der Variable
 
ausgegeben . Wenn dies nicht so ist wird die Variable ausgegeben. 
 
*FARBE=rotweis
 
*echo ${FARBE#rot}
 
weis
 
 
 
* ${PROGRAM##*/}
 
 
 
Werden ## Kreuze angeben so wird die längstmögliche Ersetzung vorgenommen und der Rest wird ausgeben.
 
*PROGRAM=/usr/bin/passwd
 
*echo ${PROGRAM#*/}
 
usr/bin/passwd
 
*echo ${PROGRAM##*/}
 
passwd
 
 
 
* ${FARBE%weis}
 
 
 
Wenn das Wort rot am Ende der Variable steht wird der restliche Anfang  der Variable ausgegeben. Wenn dies nicht so ist wird die Variable ausgegeben. 
 
 
 
*FARBE=rotweis
 
*echo ${FARBE%weis}
 
rot
 
 
 
* ${PROGRAM%%*/}
 
 
 
Werden %% (2 Prozentzeichen) angeben, so wird die längstmögliche Ersetzung vorgenommen und der Anfang  wird ausgeben.
 
*FARBE=rotweisrot
 
*echo ${FARBE%o*}
 
rotweisr
 
*echo ${FARBE%%o*}
 
r
 
 
 
* ${FARBE/rot/blau}
 
 
 
Ersetzen eines Musters. Kommt in der Variable FARBE ein rot vor, wird dies durch blau ersetzt. 
 
 
 
* ${FARBE//rot/blau}
 
 
 
Ersetzen eines Musters.  Kommen in der Variable FARBE mehrere  rot vor, werden sie durch blau ersetzt.
 
 
 
*FARBE=rotweisrot
 
*echo ${FARBE/rot/blau}
 
blauweisrot
 
*echo ${FARBE//rot/blau}
 
blauweisblau
 
 
 
=Besondere Dateien=
 
*[[Bash Dateien]]
 
 
 
=Wichtige Systemvariablen (Auswahl)=
 
; PATH
 
Pfad, in dem nach ausführbaren Programmen gesucht wird
 
; HOME
 
Heimatverzeichnis
 
; BASH
 
Pfadname der aktuellen Shell
 
; PWD
 
Aktuelles Verzeichnis
 
; OLDPWD
 
Letztes aktuelles Verzeichnis vor cd
 
; PS1 ,PS2 , PS3
 
Eingabeprompt 1 2 und 3
 
; UID
 
Benutzerkennung
 
; EDITOR
 
Standardeditor (wenn nicht belegt, dann vi)
 
; MAIL
 
Dort werden die Mails gespeichert
 
; HOSTNAME
 
Name des Rechners
 
 
 
=Stellungsparameter (Spezielle Variablen)=
 
Den Stellungsparametern $1, $2, ..., $9 werden bei ihrer Definition nach ihrer Reihenfolge Werte zugewiesen.
 
Die Definition erfolgt mit dem Kommando ''set',  einem Skript - oder Prozeduraufruf .
 
 
 
Ihr Geltungsbereich ist lokal, d.h. sie gelten nur in der aktuellen bash und können nicht exportiert werden.
 
 
 
==Belegen der Variablen mittels set==
 
*set der fck ist eine klasse Mannschaft
 
*echo $1 $2 $3
 
der fck ist
 
*echo $5 $6 $7
 
eine klasse Mannschaft
 
*set unser fcs ist aber auch ok
 
*echo $1 $2 $3
 
unser fcs ist
 
 
 
==Belegen der Variablen durch einen Skriptaufruf==
 
Die Variablen werden automatisch beim Skriptaufruf belegt, indem sie als Argumente dem Skript übergeben werden.
 
*cat skript1
 
<syntaxhighlight lang="bash">
 
#!/bin/bash
 
echo "1        parameter $1"
 
echo "2        parameter $2"
 
echo "3        parameter $3"
 
echo "4        parameter $4"
 
echo "alle    parameter $*"
 
echo "alle    parameter $@"
 
echo "anzahl    parameter $#"
 
echo "skriptname      $0"
 
echo "PID des skriptes      $$"
 
echo "Rückgabewert letztes Kommando    $?"
 
</syntaxhighlight>
 
*./skript1 blau gruen gelb rot
 
1            parameter blau
 
2            parameter gruen
 
3            parameter gelb
 
4            parameter rot
 
alle        parameter blau gruen gelb rot
 
alle        parameter blau gruen gelb rot
 
anzahl      parameter 4
 
skriptname            ./skript1
 
PID des skriptes      1019
 
Rückgabewert letztes Kommando    0
 
 
 
==Systemparameter==
 
Der Begriff Systemparameter bezeichnet eine Variable, die von der bash automatisch mit Werten versorgt wird. Die aktuellen
 
Werte können vom Benutzer abgefragt werden.
 
 
 
Einige wichtige Systemparameter:
 
 
 
 
 
{| border=1 cellpadding="2"
 
| $$
 
| PID des laufenden Prozesses
 
|-
 
| $!
 
| PID des letzten Hintergrundprozesses
 
|-
 
| $-
 
| Liste der für die bash gesetzten Schalter
 
|-
 
| $?
 
| Exitstatus des letzten Kommandos
 
|-
 
| $#
 
| Anzahl der Stellungsparameter
 
|-
 
| $*
 
| Liste der Stellungsparameter
 
|-
 
| $0
 
| Aktueller Prozessname
 
|}
 
 
 
==shift-Kommando==
 
Das Kommando bewirkt die Verschiebung aller Stellungsoperanden um eine Stelle nach links. Auf diese Weise ist
 
nach der Anwendung des shift-Kommandos der Wert des 10ten Parameters in $9, der ursprüngliche Wert von $1 ist
 
verloren. Die Stellenanzahl, um die verschoben wird, kann angegeben werden, z. B. bewirkt der Befehl ''shift 4''
 
das Verschieben um 4 Stellen nach links.
 
 
 
*set hallo ihr guten admins von der schule hier
 
*echo $1 $2 $3 $4
 
hallo ihr guten admins
 
*shift
 
*echo $1 $2 $3 $4
 
ihr guten admins von
 
*shift 3
 
*echo $1 $2 $3 $4
 
von der schule hier
 
 
 
=Here Dokument=
 
Heredocs dienen zur Definition von Textabschnitten. Im Unterschied zur herkömmlichen Ausgabe per echo  werden enthaltene Zeilenumbrüche, Einzüge und einige Sonderzeichen im Text bewahrt. Die Bash ermöglicht auch die Verwendung von Variablen innerhalb des Heredoc.
 
 
 
Der Block ab "cat<<HERE" wird bis zu "HERE" ausgegeben. Das Wort "HERE" ist beliebig. Wichtig hinter dem 2 Wort darf keine Leerzeichnen stehen.
 
<syntaxhighlight lang="bash">
 
#!/bin/bash
 
INT=$1
 
IP=$2
 
NM=$3
 
GW=$4
 
cat<<HERE
 
auto $INT
 
iface $INT inet static
 
address $IP
 
netmask $NM
 
gateway $GW
 
HERE
 
</syntaxhighlight>
 
*./interface-gen.sh eth3 192.168.24.67 255.255.255.0 192.168.24.1
 
<pre>
 
auto eth3
 
iface eth3 inet static
 
address 192.168.24.67
 
netmask 255.255.255.0
 
gateway 192.168.24.1
 
</pre>
 
 
 
=read-Kommando=
 
Mit read wird eine Eingabezeile eingelesen und deren Inhalt Variablen zugewiesen. Die Eingabe wird anhand der
 
Trennzeichen in einzelne Token zerlegt und der Reihe nach den Variablen zugewiesen. Stehen mehr Token zur
 
Verfügung als Variablen, so wird die letzte Variable mit allen noch nicht zugewiesenen  Token belegt; stehen weniger
 
Token bereit, bleibt der Inhalt der überschüssigen Variablen leer:
 
<syntaxhighlight lang="bash">
 
#!/bin/bash
 
echo "wie heißen sie?"
 
read NAME VORNAME
 
echo "Sie heißen $VORNAME $NAME"
 
</syntaxhighlight>
 
read wird in dieser Form sehr selten benutzt da der automatische Charakter von shell Skripten dadurch verloren geht.
 
 
 
=Einfache Verzweigungen=
 
In Abhängigkeit vom Returncode eines Befehls oder einer Pipe kann mit den Sonderzeichen ''&&'' und ''||''  eine
 
Verzweigung durchgeführt werden.
 
*echo ''das ist sux1.'' > sux1
 
*rm sux1 && echo ''sux1 ist geloescht!''
 
*rm sux1 || echo ''sux1 konnte nicht geloescht werden.''
 
Der Befehl nach ''&&'' wird dabei nur ausgeführt, wenn der Returncode des vorherigen Befehls oder der vorherigen
 
Pipe 0 war, also der Befehl vor der Pipe fehlerfrei ausgeführt wurde. Ist ein Befehl vor einer Pipe nicht erfolgreich
 
(Returncode != 0), wird der Befehl nach ''||'' ausgeführt.
 
 
 
=Endestatus=
 
N:ach der Ausführung eines  Befehls wird ein Returncode (Endestatus) zurückgeliefert. Mit Hilfe des Returncodes lässt
 
sich feststellen, ob der letzte Befehl fehlerfrei ausgeführt wurde.
 
Returncode = 0 Letzter Befehl wurde fehlerfrei ausgeführt.
 
Returncode ≠ 0 Letzter Befehl wurde nicht fehlerfrei ausgeführt.
 
Das Kommando ''true'' liefert den Returncode 0, ''false'' liefert den Returncode ≠ 0 .
 
Bei einigen Befehlen wird die zurückgelieferte Fehlermeldung (Returncode ≠ 0) noch weiter differenziert (siehe man
 
fsck). In der Systemvariablen $? ist der aktuelle Returncode abgelegt und kann vom Benutzer abgefragt werden.
 
Bsp.:
 
*fsck asasas
 
*echo $?
 
16
 
oder
 
*ping www.xinux.de -w 1 -c 1 > /dev/null 2>&1
 
*ping 172.20.103.2  -w 1 -c 1 > /dev/null 2>&1
 
*echo $?
 
0
 
Erkenntnis: Rechner ist erreichbar
 
 
 
*ping 172.20.103.99  -w 1 -c 1 > /dev/null 2>&1
 
*echo $?
 
1
 
Erkenntnis: Rechner ist nicht erreichbar
 
 
 
*touch bohnen
 
*rm bohnen 2> /dev/null
 
*echo $?
 
0
 
Erkenntnis: Löschen war erfolgreich
 
 
 
*rm bohnen 2> /dev/null
 
*echo $?
 
1
 
Erkenntnis: Löschen war nicht erfolgreich
 
 
 
=test-Kommando=
 
Der eingebaute Befehl ''test'' gibt sein Ergebnis als Returncode zurück. Dieser Befehl wird daher oft in
 
Kontrollstrukturen der bash zur Verzweigung verwendet.
 
 
 
Es existieren 2 Schreibweisen:
 
 
 
'''test''' bedingung
 
'''[''' bedingung ''']'''
 
 
 
Ist das von ''bedingung'' zurückgelieferte Ergebnis wahr, wird der Returncode 0 übergeben, sonst ungleich 0.
 
''bedingung'' kann ein numerischer Vergleich, ein Stringvergleich, eine Prüfung von Objekteigenschaften oder
 
eine beliebige Kombination der vorhergehenden sein.
 
 
 
==Numerischer Vergleich==
 
'''test''' zahl1 '''-op''' zahl2 (op: eq, ne, lt, gt, ge, le)
 
*ZAHL=4
 
*test $ZAHL -eq "4" && echo stimmt
 
 
 
 
 
{| border=1 cellpadding="2"
 
| -eq
 
| gleich
 
|-
 
| -ne
 
| ungleich
 
|-
 
| -lt
 
| kleiner
 
|-
 
| -gt
 
| größer
 
|-
 
| -ge
 
| größer oder gleich
 
|-
 
| -le
 
| kleiner oder gleich
 
|}
 
 
 
==Stringvergleich==
 
'''test''' string1 '''=''' string2
 
'''test''' string1 '''!=''' string2
 
'''test''' –n string  oder  test string (Länge von string größer null)
 
'''test''' –z string (Länge von string gleich null)
 
 
 
*HOBBIT=frodo
 
*'''test''' $HOBBIT '''=''' "bilbo" && echo frodo
 
*'''test''' $HOBBIT '''=''' "bilbo" && echo bilbo
 
*HOBBIT=bilbo
 
*'''test''' $HOBBIT '''=''' "bilbo" && echo bilbo
 
bilbo
 
 
 
==Objekteigenschaften==
 
'''test -op''' objekt    
 
{| border=1 cellpadding="2"
 
| d || Directory
 
|-
 
| f || Datei
 
|-
 
| s || nicht leere Datei
 
|-
 
| r || leserecht auf das Objekt
 
|-
 
| w ||  schreibrecht auf das Objekt
 
|-
 
| x || ausführungsrecht auf das Objekt
 
|}
 
 
*test -f /etc/shadow && echo sicheres system
 
sicheres system
 
*test -r /etc/shadow || echo so ist es richtig
 
so ist es richtig
 
 
 
==Prioritäten bei logischen Verknüpfungen==
 
{| border=1
 
| runde Klammer || Negation || AND || OR
 
|-
 
| '''()''' || '''!''' ||    '''-a'''  || '''-o'''
 
|}
 
 
 
 
 
test \'''(''' -r dat '''-o''' -w dat \''')'''
 
test '''!''' \'''(''' -r dat '''-o''' -w dat \''')'''
 
test ''$name'';echo $?
 
 
 
*! test -r /etc/shadow &&  echo so ist es richtig
 
so ist es richtig
 
=Optionen der Shell=
 
Die Shell hat verschiedene sehr nützliche Optionen.
 
 
 
=Man kann sie sich mit Optionen den aktuellen Shell anzeigen lassen=
 
*echo $-
 
himBHs
 
=Mit dem set kann man die Optionen setzen oder deaktivieren=
 
*set -|+optionen...
 
=Wichtige Optionen der Bash=
 
{| class="wikitable"
 
|+Optionen der Shell
 
|-
 
|f
 
|Dateinamen expandieren ausschalten
 
|-
 
|n
 
|Kommandos nur lesen und nicht ausführen
 
|-
 
|x
 
|Jedes einfache Kommando unmittelbar vor der Ausführung ausgeben. Ersetzungen werden vorgenommen
 
|-
 
|a
 
|Alle angelegten Variablen für den Export markieren
 
|-
 
|e
 
|Shell verlassen wenn ein Kommando nicht erfolgreich ausgeführt werden kann.
 
|-
 
|v
 
|Jede Zeile wird ausgegeben bevor sie ausgeführt wird
 
|-
 
| -
 
|So kann Positionsparameter setzen die mit einem - beginnen
 
|}
 
 
 
=Der if-Block=
 
'''if''' programm
 
'''then'''
 
  anweisung1
 
'''else'''
 
  anweisung2
 
'''fi'''
 
Der if-Block verzweigt in Abhängigkeit des Returncodes des Programmes das ausgeführt wird.  Ist der
 
Returncode gleich null, wird Anweisung1 ausgeführt; ist der Returncode ungleich null, wird Anweisung2
 
ausgeführt.
 
 
 
[[Image:if.jpg]]
 
 
 
Der else-Zweig kann ausgelassen oder durch einen elif-Zweig ersetzt werden. Der elif-Zweig ist eine
 
Besonderheit bei Verschachtelungen.
 
*cat rechnertest
 
<syntaxhighlight>
 
#!/bin/bash
 
if ping -c 1 -w 1 $1 > /dev/null 2>&1
 
then
 
echo "rechner lebt"
 
else
 
echo "rechner ist tot"
 
fi
 
</syntaxhighlight>
 
*./rechnertest 172.20.103.1
 
rechner lebt
 
*./rechnertest 172.20.103.99
 
rechner ist tot
 
 
 
==Variante ohne else==
 
*cat rechnertest.spar
 
<syntaxhighlight>
 
#!/bin/bash
 
if ping -c 1 -w 1 $1 > /dev/null 2>&1
 
then
 
echo "rechner lebt"
 
fi
 
</syntaxhighlight>
 
 
 
*./rechnertest.spar 172.20.103.1
 
rechner lebt
 
*./rechnertest.spar 172.20.103.99
 
 
 
==Sonderform  mit elif==
 
*cat el
 
<syntaxhighlight>
 
#!/bin/bash
 
echo -n "wie heissen Sie :"
 
read NAME
 
if test $NAME = "thomas"
 
  then
 
    echo "hallo meister"
 
elif test $NAME = "martin"
 
  then
 
    echo "hallo vizemeister"
 
else
 
    echo "hallo wurm"
 
fi
 
</syntaxhighlight>
 
*./el
 
wie heissen Sie :thomas
 
hallo meister
 
*./el
 
wie heissen Sie :martin
 
hallo vizemeister
 
*./el
 
wie heissen Sie :suxer
 
hallo wurm
 
 
 
=Der case-Block=
 
Der case-Block dient der Durchführung eines Stringvergleiches. Er wird sequentiell von oben nach unten abgearbeitet. Bei
 
Übereinstimmungen mit einem definierten Muster wird der darauf folgende Befehl ausgeführt (bzw. die darauf folgende
 
Befehlsliste). Bei der ersten gefundenen Übereinstimmung terminiert der case-Block.
 
 
 
Bei der Definition des Musters können die Sonderzeichen der bash zur Dateinamengenerierung verwendet werden. Zusätzlich
 
kann ''|'' für eine logische OR-Verknüpfung benutzt werden.
 
 
 
*cat case1
 
<syntaxhighlight>
 
#!/bin/bash
 
case $1 in
 
  rock|rocknroll)
 
    echo "stones sind gut"
 
  ;;
 
  schlager)
 
    echo "guildo ist ein gott"
 
  ;;
 
  volks)
 
    echo "was an der waffel?"
 
  ;;
 
  *)
 
    echo "kein bock auf musik"
 
  ;;
 
esac
 
</syntaxhighlight>
 
*./case1 rock
 
stones sind gut
 
*./case1 rocknroll
 
stones sind gut
 
*./case1 schlager
 
guildo ist der meister
 
*./case1 volks
 
was an der waffel?
 
*./case1 kllkjl
 
kein bock auf musik
 
 
 
=Rechnen mit der Bash=
 
; '''$(())'''
 
; '''expr'''
 
; '''bc'''
 
==Arithmetische Substitution==
 
Die $(()) oder $[ ] ist die arithmetische Erweiterungsmethode  der Bash.
 
*echo $((7+5))
 
12
 
*echo $((7*5))
 
35
 
*echo $((7/5))
 
1
 
*echo $((7-5))
 
2
 
*echo $((7%5))
 
2
 
*ZAHL=5 ; ZAHL=$(($ZAHL + 1)) ; echo $ZAHL
 
6
 
==Der expr-Befehl==
 
Erlaubt die Durchführung komplexer Stringoperationen und Ganzzahlarithme­tik.
 
*expr 7 + 5
 
12
 
*expr 7 \* 5
 
35
 
*expr 7 / 5
 
1
 
*expr 7 – 5
 
2
 
*expr 7 % 5
 
2
 
*ZAHL=5 ; ZAHL=$(expr $ZAHL + 1) ; echo $ZAHL
 
6
 
==bc - interaktiver Taschenrechner==
 
*bc
 
bc 1.06
 
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
 
This is free software with ABSOLUTELY NO WARRANTY.
 
For details type `warranty'.
 
12 * 3
 
36
 
quit
 
 
 
Mit der Option -l wird die mathematische Bibliothek eingeschaltet
 
 
 
*bc -l
 
bc 1.06
 
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
 
This is free software with ABSOLUTELY NO WARRANTY.
 
For details type `warranty'.
 
7 / 5
 
1.40000000000000000000
 
quit
 
 
 
Da bc auch von STDIN lesen kann, kann man es auch in Shellskripten benutzen.
 
 
 
*echo 7/5 | bc -l
 
1.40000000000000000000
 
 
 
*ZAHL=5 ; ZAHL=$(echo $ZAHL+1 | bc -l) ; echo $ZAHL
 
6
 
 
 
=Die while-Schleife=
 
==Einfache Form==
 
Die while-Schleife wird so lange durchlaufen, bis der Returncode ungleich null ist.
 
*cat proggi
 
<syntaxhighlight>
 
#!/bin/bash
 
while [ $# -ge 1 ]
 
do
 
  echo $1
 
  echo $#
 
  shift
 
done
 
</syntaxhighlight>
 
 
 
*./proggi blau gelb gruen
 
blau
 
3
 
gelb
 
2
 
gruen
 
1
 
 
 
Darstellung als Struktogramm nach Nassi / Shneiderman:
 
 
 
[[Image:while.jpg]]
 
 
 
Beispiel:
 
<syntaxhighlight>
 
#!/bin/bash
 
COUNTER=$1
 
while [ $COUNTER -ge 1 ]
 
  do
 
  echo $COUNTER
 
  COUNTER=$(($COUNTER-1))
 
done
 
echo "BUMM BUMM"
 
</syntaxhighlight>
 
*./countdown 5
 
5
 
4
 
3
 
2
 
1
 
BUMM BUMM
 
 
 
==Sonderform von while==
 
Die Variable SUX wird nacheinander mit jeder Zeile der Datei
 
/etc/passwd belegt, bis die letzte Zeile der Datei /etc/passwd erreicht ist.
 
<syntaxhighlight>
 
#!/bin/bash
 
while read SUX
 
do
 
echo $SUX
 
done  <  /etc/passwd
 
</syntaxhighlight>
 
Selbstgebautes cat
 
<syntaxhighlight>
 
#!/bin/bash
 
while read ZEILE
 
do
 
  echo $ZEILE
 
done < $1
 
</syntaxhighlight>
 
Selbstgebautes tac
 
<syntaxhighlight>
 
#!/bin/bash
 
COUNT=0
 
while read ZEILE
 
do
 
FELD[$COUNT]=$ZEILE
 
COUNT=$(($COUNT+1))
 
done < $1
 
while [ $COUNT -ge 0 ]
 
do
 
echo ${FELD[$COUNT]}
 
COUNT=$(($COUNT-1))
 
done
 
</syntaxhighlight>
 
=Die until-Schleife=
 
 
 
Die until-Schleife wird so lange durchlaufen, bis der Returncode der Abbruchbedingung gleich null ist.
 
 
 
'''until''' test ''$# -eq 0
 
'''do'''
 
    echo $1
 
    shift
 
'''done'''
 
 
 
Darstellung als Struktogramm nach Nassi / Shneiderman:
 
 
 
[[Image:until.jpg]]
 
 
 
= Die for-Schleife =
 
==Standard For Schleife==
 
Bei der for-Schleife wird bei jedem Durchlauf der Schleifenvariablen ein Wert aus einer angegebenen Liste
 
zugewiesen; die Liste wird dabei von links nach rechts durchlaufen. Nach der letzten Wertzuweisung terminiert die
 
for-Schleife.
 
 
 
*cat fussball
 
<syntaxhighlight lang="bash">
 
#!/bin/bash
 
for CLUB in fck bvb schalke bmg
 
  do
 
  echo $CLUB
 
done
 
</syntaxhighlight>
 
*./fussball
 
fck
 
bvb
 
schalke
 
bmg
 
 
 
Darstellung als Struktogramm nach Nassi / Shneiderman:
 
 
 
[[Image:for.jpg]]
 
 
 
==For Schleife mit Stellungsparametern==
 
Wird keine Liste angegeben, wird standardmäßig die Liste der Stellungsoperanden benutzt. Folgende Anweisungen sind äquivalent
 
<syntaxhighlight>
 
#!/bin/bash
 
for LAUF in $*
 
do
 
  echo $LAUF
 
done
 
</syntaxhighlight>
 
Kurzform :
 
<syntaxhighlight>
 
for LAUF
 
do
 
  echo $LAUF
 
done
 
</syntaxhighlight>
 
 
 
==For Schleife mit Dateien aus dem aktuellen Verzeichnis==
 
Der Stern würde durch alle Dateien des aktuellen Verzeichnisses ersetzt werden.
 
Daraus folgt, dass der Name jeder Datei nacheinander in die Variable LAUF geschreiben wird. Die Anzahl der Schleifenläufe
 
ist identisch mit der Anzahl von Dateien.
 
<syntaxhighlight>
 
#!/bin/bash
 
for LAUF in *
 
do
 
echo $LAUF
 
done
 
</syntaxhighlight>
 
Hier die Variante mit einem grossen K
 
<syntaxhighlight>
 
#!/bin/bash
 
for LAUF in K*
 
do
 
echo $LAUF
 
done
 
</syntaxhighlight>
 
==For Schleife im C Stil==
 
Mit Bash-Version 2.0.4 wurde die for-Schleife um eine an die Programmier-sprache C angelehnte Syntaxvariante erweitert:
 
 
 
for ((Initialisierung der Laufvaribale; Laufbedingung; Veränderung der Laufvariable))
 
do
 
Kommando
 
done
 
*cat foor
 
<syntaxhighlight>
 
#!/bin/bash
 
for ((I=1;I<5;I++))
 
do
 
echo $I
 
done
 
</syntaxhighlight>
 
*./foor
 
1
 
2
 
3
 
4
 
 
 
=Steuerung der Ablaufanweisungen=
 
==exit n==
 
Der aktuelle Prozess und damit auch die bash werden abgebrochen. Für n kann eine Zahl zwischen 0 und 255 angegeben werden;
 
damit kann der Returncode des Prozesses festgelegt werden, der an den aufrufenden Prozess übergeben wird.
 
 
 
Zur Schleifensteuerung können die Befehle ''continue'' und ''break'' verwendet werden. Sie dürfen nur zwischen den
 
Schlüsselwörtern ''do'' und ''done'' stehen.
 
 
 
==continue n==
 
Der aktuelle Schleifendurchlauf wird abgebrochen, um mit dem nächsten Durchlauf zu beginnen. Bei Verschachtelungen kann
 
durch Angabe einer Ganzzahl in der n-ten Schleifenebene angesetzt werden.
 
<syntaxhighlight>
 
#!/bin/bash
 
for CLUB in fck bvb bayern fcs
 
do
 
  if [ $CLUB = "bayern" ]
 
  then
 
    echo "zeig ich nicht an"
 
    continue
 
    exit
 
  fi
 
echo $CLUB
 
done
 
</syntaxhighlight>
 
*./fussball
 
fck
 
bvb
 
zeig ich nicht an
 
fcs
 
 
 
=Select=
 
Mit dem Befehl bash select können verschiedene Arten von Menüerstellungsaufgaben, das Erstellen einer menübasierten Listen, das Erstellen eines Menüs aus Dateiinhalten usw. ausgeführt werden.
 
 
 
 
 
<syntaxhighlight>
 
#!/bin/bash
 
select auswahl in Punkt1 Punkt2 Punkt3 Punkt4
 
do
 
  echo "Ihre Auswahl war : $auswahl"
 
done
 
</syntaxhighlight>
 
 
 
<syntaxhighlight>
 
#!/bin/bash
 
PS3="Datei zum Editieren auswählen : "
 
select AUSWAHL in *.sh exit
 
do
 
  case "$AUSWAHL" in
 
      exit)
 
          echo "exit"
 
          break
 
          ;;
 
        "")
 
          echo "$REPLY: Ungültige Auswahl"
 
          ;;
 
        *)
 
            if [ -d "$AUSWAHL" ]
 
              then
 
                echo "Verzeichnis kann nicht editiert werden"
 
                continue
 
              else
 
                $EDITOR $AUSWAHL
 
              fi
 
              break
 
            ;;
 
  esac
 
done
 
</syntaxhighlight>
 
 
 
 
 
 
 
 
 
==break n==
 
Die aktuelle Schleife wird abgebrochen, danach wird mit der ersten Anweisung nach der Schleife weitergemacht. Bei
 
Verschachtelungen wird auf der n-ten Schleifenebene aufgesetzt.
 
 
 
Anmerkung:
 
Ein sinnvoller Einsatz dieser Konstrukte liegt in der Behandlung von Ausnahmen (Fehler). Intensiver Einsatz macht die
 
Programme unleserlich und schwer kontrollierbar. Daher ist eine sparsame Verwendung empfehlenswert.
 
 
 
<syntaxhighlight>
 
#!/bin/bash
 
while true
 
do
 
  test -f /tmp/sux && break 
 
  echo "unn weiter"
 
  sleep 3
 
done
 
echo  "und tschuess"
 
</syntaxhighlight>
 
 
 
=Funktionen=
 
[[bash funktion]]
 
 
 
=Signalbehandlung=
 
==Signale bei der Programmierung der bash==
 
Es existieren verschiedene Möglichkeiten, auf welchem Wege Signale gesendet werden können:
 
 
 
# von aussen:
 
## Benutzer (< DEL >, < CTRL >|, etc.)
 
## Prozesse (kill, alarm)
 
# von innen:
 
## Programmfehler (Adressfehler, ungültiger Befehl, Division durch 0, etc.)
 
 
 
Signale dienen der Interprozesskommunikation. Diese Nachrichten beschränken sich allerdings auf die Übertragung eines einzigen Wertes.
 
 
Von den Befehlen ''trap'' und ''kill'' werden folgende Signale verwendet:
 
 
 
{| border="1" cellpadding="2"
 
! Signalnummer
 
! Bedeutung
 
|-
 
| 0
 
| Beenden von bash
 
|-
 
| SIGHUP 1
 
| Logoff von einer Datensichtstation
 
|-
 
| SIGINT 2
 
| Drücken der Taste < DEL >
 
|-
 
| SIGQUIT 3
 
| Drücken der Taste < CTRL > + c
 
|-
 
| SIGKILL 9
 
| kill: unbedingter Prozessabbruch
 
|-
 
| SIGTERM 15
 
| Programmbeendigung
 
|}
 
 
 
==Reaktion eines Prozesses auf den Empfang eines Signals==
 
* Der Prozess beendet sich (meist Standardeinstellung).
 
* Der Prozess ignoriert das Signal. (Ausnahme: SIGKILL)
 
* Der Prozess fängt das Signal ab, d.h. er leitet eine selbst definierte Reaktion ein.
 
 
 
=Der Befehl trap =
 
'''Funktionen:'''
 
 
 
;Signalbehandlung setzen
 
(Nach Beendigung der bash werden die betreffenden temporären Dateien gelöscht)
 
*trap 'rm *.tmp' 0
 
*trap 'who; exit 1' 2 3
 
 
;Liefern von Informationen über gesetzte Signalbehandlung
 
*trap
 
 
 
;Zurücksetzen der Signalbehandlung
 
*trap 2 3
 
 
 
;Import von Signalen
 
*trap : 2 3
 
*trap '' 2 3
 
 
 
;Demonstriert die Funktion trap zum Abfangen von Signalen
 
<syntaxhighlight>
 
#!/bin/bash
 
trap 'echo trap ausgelöst' 2
 
i=0
 
while [ $i -lt 5 ]
 
do
 
  echo "Bitte nicht stören!"
 
  sleep 2
 
  i=`expr $i + 1`
 
done
 
</syntaxhighlight>
 
Bemerkung: Die Signalbehandlung selbst wird nicht an Kindprozesse weitervererbt. Das Ignorieren von Signalen hingegen wird weitervererbt.
 
 
 
=Weitere Möglichkeiten der Bash-Shell=
 
==Alias-Namen==
 
*[[aliase]]
 
 
 
=Filedeskriptoren=
 
==Schreibenden Deskriptor==
 
;anlegen
 
*exec 5> /tmp/five
 
;rein schreiben
 
*echo eins >&5
 
*echo zwei >&5
 
*echo drei >&5
 
;ausgeben
 
*cat /tmp/five
 
;aufheben
 
*exec 5>&-
 
;führt zu Fehler
 
*echo vier >&5
 
==Lesender Deskriptor==
 
;anlegen
 
*exec 7< /etc/hosts
 
;auslesen
 
*cat <&7
 
;geht nur einmal
 
*cat <&7
 
 
 
==Gleichzeitiges Lesen aus verschiedenen Dateien==
 
<syntaxhighlight>
 
#!/bin/bash
 
exec 3< /etc/passwd
 
exec 4< /etc/shadow
 
while true
 
do
 
  read var3 <&3
 
  read var4  <&4
 
  echo passwd  $var3
 
  echo shadow $var4 ;
 
  test -z $var4 && break
 
done
 
</syntaxhighlight>
 
==Gleichzeitiges Lesen aus Datei und Standardeingabe==
 
<syntaxhighlight>
 
#!/bin/bash
 
exec 3< $1
 
while read line <&3
 
do
 
  echo $line
 
  printf "Eine weitere Zeile einlesen? [j/n] : "
 
  read REPLY
 
  test "$REPLY" = "n"  && break
 
done
 
</syntaxhighlight>
 
 
 
=Bearbeiten von Farben=
 
 
 
Um die Farben in der Shell zu ändern, müssen wir bestimmte Zeichenfolgen senden. Die Zeichenkette \033\13301;31m würde z.B. alles Weitere in Rot ausgeben.
 
 
 
Format: \033\133;m
 
 
 
Diese Methode kann allerdings beim Setzen der Variable $PS1, die den Prompt kontrolliert, dazu führen, dass der Zeilenumbruch falsch berechnet wird. Deshalb ist in diesem Fall der Einschluss in \[ \] erforderlich.
 
 
 
Format: \[\033\133;m\]
 
 
 
Um mit dem Farbigen aufzuhören und wieder normal zu schreiben sendet man einfach folgende Zeichenfolge:
 
 
 
\033\1330m
 
 
 
Textdekorationen:
 
00 - Schmaldruck
 
01 - Keine
 
02 - dunkle Version der Farbe
 
04 - Unterstreichen
 
05 - Invertieren
 
 
 
Farben:
 
30 - Schwarz
 
31 - Rot
 
32 - Grün
 
33 - Gelb
 
34 - Blau
 
35 - Lila
 
36 - Cyan
 
37 - Grau
 
 
 
Hintergründe färben:
 
40 - Schwarz
 
41 - Rot
 
42 - Grün
 
43 - Gelb
 
44 - Blau
 
45 - Lila
 
46 - Cyan
 
47 - Grau
 
 
 
Austesten wie es dann genau aussieht kann man das mit den folgenden Befehlen:
 
 
 
for i in `seq 40 47`;do echo -e "Farbnummer:\033\13301;"$i"m $i \033\01330m";done
 
for i in `seq 30 37`;do echo -e "Farbnummer:\033\13301;"$i"m $i \033\01330m";done
 
 
 
=getopts=
 
<syntaxhighlight>
 
#!/bin/bash
 
function examine()
 
{
 
FILE=$1
 
shift
 
echo "Rights on $FILE"
 
for k in $*
 
do
 
case $k in
 
u) echo USER : $(ls -l $FILE | cut -c 1-3) ;;
 
g) echo GROUP: $(ls -l $FILE | cut -c 4-6) ;;
 
o) echo OTHER: $(ls -l $FILE | cut -c 7-9) ;;
 
esac
 
done
 
}
 
while getopts ugof: opt
 
do
 
  case $opt in
 
      u) OPT="${OPT} u";;
 
      g) OPT="${OPT} g";;
 
      o) OPT="${OPT} o";;
 
      f) DAT=$OPTARG;;
 
      ?) echo "USAGE: $0 -ugo -f FILE"; exit 2 ;;
 
  esac
 
done
 
examine $DAT $OPT
 
</syntaxhighlight>
 
;Erklärung
 
*Das Program kann mit den Optionen -u -g -o und -f Datei aufgerufen werden.
 
*Die Optionen ugo werden in der Variable $OPT "gesammelt".
 
*Alle Optionen werden an die Funktion examine übergeben.
 
*Die Optionen werden oben getrennt und je nach vorhandener Option werden Anweisungen ausgeführt.
 
 
 
 
 
*http://openbook.galileocomputing.de/shell_programmierung/shell_005_007.htm
 
 
 
=printf=
 
Formatierte Ausgabe mit printf
 
 
 
Im einfachsten Fall wird ein fester Text auf dem Bildschirm ausgegeben:
 
*printf("Dies ist ein einfaches Beispiel");
 
Der Text kann auch Sonderzeichen (z. B. Zeilenumbrüche) enthalten:
 
*printf("Hier werden \n zwei Zeilen ausgegeben!");
 
Die Zeichensequenz \n bewirkt einen Sprung an den Anfang der folgenden Bildschirmzeile. Weitere gebräuchliche Sonderzeichen sind:
 
{| class="wikitable"
 
|-
 
|\n
 
|Sprung an den Anfang der folgenden Bildschirmzeile
 
|-
 
|\b
 
|Gehe ein Zeichen zurück
 
|-
 
|\a
 
|Akustisches Signal
 
|-
 
|\r
 
|Sprung an den Anfang der aktuellen Bildschirmzeile
 
|-
 
|\\
 
|Ausgabe des Gegenschrägstrichs "\" (Backslash)
 
|-
 
|%%
 
|Ausgabe des Prozent-Zeichens "%"
 
|-
 
|\"
 
|Ausgabe eines doppelten Anführungszeichens
 
|-
 
|\t
 
|Sprung zur nächsten Tabulatorposition
 
|}
 
Sollen aktuelle Variablenwerte ausgegeben werden, werden in den Aufruf der
 
 
 
Funktion printf entsprechende „Platzhalter“ eingefügt:
 
*int x = 10;
 
*printf("Der Wert %d wurde der Variablen x zugewiesen.", x);
 
Auf dem Bildschirm erfolgt die Ausgabe „Der Wert 10 wurde der Variablen x zugewiesen“, es wird also der Platzhalter %d durch den aktuellen Wert der Variablen x
 
ersetzt. Es ist möglich, mehrere Variablen zugleich auszugeben:
 
*int x = 123, y = 234;
 
*printf("x = %d und y = %d", x, y);
 
Die Ausgabe lautet in diesem Fall „x = 123 und y = 234“. Für jede Variable ist ein
 
eigener Platzhalter (hier: %d) notwendig. Die auszugebenden Variablen werden
 
durch Kommas getrennt aufgelistet. Für jeden Platzhalter muss dabei eine Variable angegeben werden (hier: x, y).
 
Es ist zu beachten, dass der Platzhalter zum Typ der auszugebenden Variablen
 
passt (z. B. dient %d zur Ausgabe einer Variablen des Typs int, short oder long).
 
Weitere Platzhalter sind:
 
 
 
{| class="wikitable"
 
|-
 
|%d, %i
 
|int, short, long
 
|Ganze Zahl
 
|-
 
|%x, %X
 
|int, short, long
 
|Ganze Zahl, Ausgabe als Hexadezimalzahl
 
|-
 
|%f
 
|float, double
 
|Fließkommazahl
 
|-
 
|%e, %E
 
|float, double
 
|Fließkommazahl, Ausgabe im Exponentialformat
 
|-
 
|%c
 
|char
 
|Einzelnes Zeichen (Buchstabe, Ziffer, …)
 
|-
 
|%s
 
|char*
 
|Zeichenkette („String“)
 
|}
 
;Beispiel:
 
*int i = 10; double d = 22.22; char c = 'X';
 
*char* str = "abcdefg...";
 
*printf("Beispiel zu printf:\n");
 
*printf("%d, %f, %c\n", i, d, c);
 
*printf("%s", str);
 
Es kann die Breite des Ausgabebereichs angegeben werden. So wird mit %10d
 
eine ganze Zahl rechtsbündig in einem Bereich von 10 Zeichen Länge ausgegeben:
 
int i = 123;
 
*printf("->%d<-\n", i);
 
*printf("->%4d<-\n", i);
 
*printf("->%5d<-\n", i);
 
Bei der Ausgabe von Fließkommazahlen kann zusätzlich zur Länge des Ausgabebereichs die Anzahl der Nachkommastellen eingestellt werden:
 
*float f = 123.625;
 
*printf("->%f<-\n", f);
 
*printf("->%.2f<-\n", f);
 
*printf("->%10.0f<-\n", f);
 
*printf("->%10.1f<-\n", f);
 
*printf("->%10.2f<-\n", f);
 
*printf("->%10.3f<-\n", f);
 
*printf("->%10.4f<-\n", f)
 
==Beispielskript==
 
<syntaxhighlight>
 
#!/bin/bash
 
for DIR in $(df -t ext4  | awk 'NR>1 {  print $6 }')
 
do
 
  PROZENT=$(df -t ext4 $DIR | awk 'NR>1 {  print $5 }')
 
  PRO=$(echo $PROZENT | tr -d "%")
 
  let KI=PRO*20/100
 
  let MI=20-KI
 
    K="####################"
 
    M='--------------------'
 
  printf "%-10s%-4s%.${KI}s%.${MI}s" $DIR $PROZENT $K $M
 
    echo
 
done
 
</syntaxhighlight>
 
==Links==
 
*https://linuxconfig.org/bash-printf-syntax-basics-with-examples
 
 
 
=Das neue Test Kommando=
 
*"[[" ist Bashs Verbesserung des "[" Befehls.
 
*Es ist die bessere  Wahl, wenn Sie Skripte schreiben, die auf Bash abzielen. Meine Favoriten sind:
 
*Es ist eine syntaktische Funktion der Shell, daher weist sie ein besonderes Verhalten auf, das "[" nicht hat.
 
*Variablen müssen nicht mehr quotiert werden, da leere Zeichenfolgen und Zeichenfolgen mit Leerzeichen intuitiver behandelt werden.
 
*Zum Beispiel müssen Sie mit "[" schreiben.
 
<pre>
 
if [ -f "$ FILE"]
 
</pre>
 
*um leere Zeichenfolgen oder Dateinamen mit Leerzeichen richtig zu behandeln. Mit "[[" sind die Anführungszeichen unnötig:
 
<pre>
 
if [[ -f $ FILE ]]
 
</pre>
 
*Da es sich um eine syntaktische Funktion handelt, können Sie && und || verwenden Operatoren für Boolesche Tests und <und> für Zeichenfolgenvergleiche.
 
*[ kann dies nicht tun, da es sich um einen regulären Befehl handelt und &&, ||, <und> nicht als Befehlszeilenargumente an reguläre Befehle übergeben werden.
 
 
 
*Es hat einen wunderbaren Operator = ~, um Übereinstimmungen mit regulären Ausdrücken zu erstellen. Mit [ könntest du schreiben
 
<pre>
 
if ["$ ANSWER" = y -o "$ ANSWER" = yes]
 
</pre>
 
*Mit [[ können Sie dies als schreiben
 
<pre>
 
if [[ $ ANSWER = ~ ^ y (es)? ]]
 
</pre>
 
*Sie können sogar auf die erfassten Gruppen zugreifen, die in BASH_REMATCH gespeichert sind.
 
*Zum Beispiel wäre $ {BASH_REMATCH [1]} "es", wenn Sie oben ein vollständiges "ja" eingeben.
 
*Sie erhalten die Mustererkennung aka Globbing kostenlos.
 
*Vielleicht sind Sie weniger streng im Schreiben von Ja. Vielleicht bist du okay, wenn der Benutzer y-irgendetwas eingibt. Haben Sie sich versichert:
 
*wenn $ ANSWER = y *
 
 
 
=Links=
 
*http://openbook.rheinwerk-verlag.de/shell_programmierung/
 
*http://mywiki.wooledge.org/BashFAQ/031
 
*http://tldp.org/LDP/abs/html/index.html
 
*http://openbook.rheinwerk-verlag.de/shell_programmierung/shell_006_003.htm
 
*https://kuepper.userweb.mwn.de/informatik/printf.pdf
 

Aktuelle Version vom 9. Juni 2023, 06:25 Uhr