Shell-Skript-Programmierung

Message
Author
Felix2000
Posts: 35
Joined: 06. Oct 2008 14:31

Shell-Skript-Programmierung

#1 Post by Felix2000 »

Ich habe mir dazu das Buch "Einführung in die Bash-Shell" vom O´Reilly Verlag besorgt. Hier wird ein Codebeispiel im Buch durchgenommen, dass ich auch anhand der Erklärung im Buch nicht ganz verstehe.

Hier der Code:

Code: Select all

pushd()
{
   dirname=$1
   DIR_STACK="$dirname ${DIR_STACK:-$PWD' '}"
   cd ${dirname:?"fehlender Verzeichnisname."}
   echo "$DIR_STACK"
} 
Ich verstehe hier nicht ganz diese Zeile: DIR_STACK="$dirname ${DIR_STACK:-$PWD' '}"

Wie genau arbeiten hier $dirname und ${DIR_STACK:-$PWD' '} zusammen? Ich habe herausbekommen, dass DIR_STACK eine Umgebungsvariable ist. Vielleicht könnt ihr mir die Codezeile erklären?

Vielen Dank

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#2 Post by Janka »

dirname, DIR_STACK und PWD sind in diesem Skript Umgebungsvariablen. PWD ist eine von der Shell automatisch auf das aktuelle Verzeichnis gesetzte Variable.
${DIR_STACK:-$PWD' '} gibt den Inhalt der Variablen DIR_STACK zurück, falls diese gesetzt ist, sonst das Ergebnis des Ausdrucks $PWD' '.

Die bash-Manpage ist hier sehr hilfreich, da sind diese Auswerte-Konstrukte beschrieben.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

Felix2000
Posts: 35
Joined: 06. Oct 2008 14:31

#3 Post by Felix2000 »

Hallo Janka !

Danke für Dein Post! Am besten ich formuliere die Frage nochmal etwas um: Warum stehen $dirname und ${DIR_STACK:-$PWD' '} direkt hintereinander? Ist ${DIR_STACK:-$PWD' '} etwas eine Option für $dirname ? Ich verstehe nicht ganz wie das zu interpretieren ist?

Wie der Ausdruck ${DIR_STACK:-$PWD' '} innerhalb eines Skriptes ausgewertet wird, ist sehr gut im oreilly Buch beschrieben, aber leider nicht der gesamte Ausdruck "$dirname und ${DIR_STACK:-$PWD' '} "

Grüße
Felix

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#4 Post by Janka »

$dirname ist kein Befehl, sondern einfach der Inhalt der Variable "dirname". Schreibt man in der Shell Quotes ("), so wird alles in den Quotes als ein String interpretiert, Referenzen werden ausgewertet. Außer den Quotes gibt es auch noch die Ticks ('), diese begrenzen auch Strings, allerdings werden keine Referenzen dazwischen ausgewertet.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

Felix2000
Posts: 35
Joined: 06. Oct 2008 14:31

#5 Post by Felix2000 »

Ok danke Janka !

Mal was anderes: Gibt es eigentlich irgendwo eine brauchbare Internetseite, auf der viele Befehle inkl. der gültigen Reihenfolge ihrer Argumente aufgelistet und erklärt werden? Irgendwie finde ich es ziemlich undurchsichtig, mir die Grundlagen der Shell-Programmierung anzueignen.

Das folgende Kommando z.B.

Code: Select all

find . -perm 600 -exec chmod g+rw {} \;
Hier steht ja die {} z.B. für die Liste, die find mir zurückgibt. Glaube ich zumindest. Wie gesagt solche Dinge würde ich gerne irgendwo nachlesen. Gibt es so etwas wie eine große Doku, die vielleicht ähnlich wie eine Beschreibung von diversen Klassen und Methoden bei Java aufgebaut ist?

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#6 Post by Janka »

Es gibt für fast jeden Befehl eine Handbuchseite. Diese erhältst du mit "man Befehl" oder im Konqueror über #Befehl. Oft gibt es auch eine Infoseite, diese erhältst du mit "info Befehl" oder im Konqueror über "##Befehl".

Außerdem kannst du Manpages im Internet lesen. Z.B. bei http://www.freebsd.org/cgi/man.cgi

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

Felix2000
Posts: 35
Joined: 06. Oct 2008 14:31

#7 Post by Felix2000 »

Super vielen Dank !!

Felix2000
Posts: 35
Joined: 06. Oct 2008 14:31

#8 Post by Felix2000 »

Hallo !

Hab nochmal eine Frage, wann genau muss ich in If, For oder While Schleifen mit den eckigen Klammern arbeiten? Manchmal finde ich Beispiele, wo eckige Klammern gesetzt sind und manchmal welche, wo darauf verzichtet wird. :(

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#9 Post by Janka »

Die eckigen Klammern entsprechen dem in der Shell eingbauten Befehl "test" -- übrigens ein guter Grund, eigene Programme niemals "test" zu nennen.

Wenn $a gleich $b dann tu c kann man also z.B wie folgt schreiben:

Code: Select all

if test "$a" = "$b"
then
  c
fi

if [ "$a" = "$b" ]
then
  c
fi

[ "$a" = "$b" ] && c
etc. etc.

Der test-Befehl macht etwas mit seinen Argumenten und liefert "0" oder "nicht 0" zurück. "if" seinerseits vergleicht nur auf "0" oder "nicht 0". Genauso macht das "&&".

Du kannst statt test auch jeden anderen Befehl nehmen, der "0" oder "nicht 0" zurückliefert. Üblicherweise liefern Befehle "0" zurück, wenn sie erfolgreich beendet werden konnten. Oft gesehenes Beispiel

Code: Select all

$ ./configure && make && sudo make install
Also ./configure ausführen, falls dies geklappt hat, make ausführen, falls dies geklappt hat sudo make install ausführen.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

Felix2000
Posts: 35
Joined: 06. Oct 2008 14:31

#10 Post by Felix2000 »

Vielen Dank ! Das muss man erstmal wissen ! Wie genau verhält sich denn der "test" wenn ich versuche mit Negationen zu arbeiten? Also bspw.

Code: Select all

if ! [ $a && $b ] then

blabla
oder so

Code: Select all

if  [ ! $a && $b ] then

blabla
Muss die then-Anweisung eigentlich immer auf der Höhe der If Anweisung stehen?

Grüße
Felix

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#11 Post by Janka »

Es geht beides, da "!" ebenfalls ein Kommando ist. Es wertet das nachfolgende Kommando aus und macht aus "0" "nicht 0", und umgekehrt. Im test-Kommando ist ! wird als Negationsoperator ausgewertet.

Code: Select all

$ ! true ; echo $?
$ ! false ; echo $?
then kann auch auf einer eigenen Zeile stehen. Probier es doch einfach aus!

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

Felix2000
Posts: 35
Joined: 06. Oct 2008 14:31

#12 Post by Felix2000 »

Hallo Janka !

Ich muss dich nochmal etwas fragen. Ich habe in vielen Shell Skripten gesehen, dass Variablen oft so geschrieben werden, bspw. in Testbefehlen, IF Anweisungen, while Schleifen usw.

"$@" oder so "$dirname" oder so "$2"

Hier nochmal zwei weitere Beispiele:

Code: Select all

if [ -d "$2" ]
then

blabla

fi
oder

Code: Select all

if [ -r "$1" ]
then

blabla

fi
Warum maskiert man manche Variablen so? Was genau habe ich davon für einen Nutzen? Ich gehe davon aus, dass es sich um Variablen in irgendwelchen Shellskripten handelt.

Viele Grüße
Felix

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#13 Post by Janka »

Sinnvoll ist das nur beim Vergleichen zweier Werte. Wenn die Variable den Leerstring enthält oder einfach nicht definiert ist meckert "test" nämlich sonst rum, dass es nur einen einzigen Parameter hätte.

$ A=
$ [ $A = X ]
bash: [: =: unary operator expected

Janka
Last edited by Janka on 07. Dec 2008 21:10, edited 1 time in total.
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

Felix2000
Posts: 35
Joined: 06. Oct 2008 14:31

#14 Post by Felix2000 »

Ok, aber es ist auch nicht grundsätzlich falsch, wenn ich mit maskierten Variablen arbeite!? Mal davon abgesehen, ob es sinnvoll ist oder nicht. Tut mir leid, dein Beispiel verstehe ich nicht ganz :?

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#15 Post by Janka »

Wenn du grundsätzlich "" drummachst, passiert bei "test" zumindest nichts Schlimmes. Es zeigt aber dem Leser des Skriptes, dass der Ersteller keine Ahnung hat, was er tut und warum.

Wenn du das Beispiel nicht verstehst, probier das Gegenbeispiel:

$ A=
$ [ "$A" = X ]

Hier gibt es nämlich *keine* Fehlermeldung.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

Post Reply