bash expansion

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
meandtheshell
Beiträge: 4054
Registriert: 14.01.2005 17:51:30

bash expansion

Beitrag von meandtheshell » 15.02.2006 20:13:16

hallo,
kennt jemand eine Möglichkeit das man angezeigt bekommt was der Reihe nach passiert wenn die bash Tokens die man in der command line eingibt auswertet.
Warum:
konkret geht es mir um das Thema bash expansion mit folgendem Beispiel

Code: Alles auswählen

prog="`basename \"$0\"`"
allgemein funktionniert die bash expansion der Reihe nach so:
Klammern Expansion
Tilde Expansion
Parameter bzw. Variabel Expansion
Arithmetrische Expansion
Kommando Substitution
Word Zerlegung
Datei Expansion
Entfernen der Quotes


Während der Schritte Parameter bis Kommando Substitution kann noch Prozess Substitution erfolgen.
So tivial der obige Ausdruck auch aussieht ich kann ihn nicht zu 100% nachvollziehen - ich versuche es einmal. Jemand der den Fehler sieht bitte Meldung machen.

Start:

Variable Expansion von $0
prog="`basename \"$0\"`"
wird zu
prog="`basename \"bash\"`"

der Backslash escaped das double qoute d.h. die double qoutes verlieren ihre Bedeutung und sind nur mehr normale Zeichen
prog="`basename \"bash\"`"

es folgt ein qoute removal welches die backslashes wegräumt
prog="`basename \"bash\"`"
wird zu
prog="`basename "bash"`"

jetzt erfolgt die Kommando Substitution
prog="`basename "bash"`"
wird hier zu
prog=""bash""

Was passiert dann? wieder ein qoute removal der alle vorhandenen qoutes wegräumt d.h. aus
prog=""bash""
wird
prog=bash was bedeutet das in der Variable prog der String bash steht.

Praxistest:

Wenn man es in der bash aufruft sieht es so aus:

Code: Alles auswählen

max@pc1:~$ var="`basename \"$0\"`";echo $var
bash
max@pc1:~$
aber warum mache ich hier nicht gleich (die folgende ist im falle das der Positions Parameter nicht nur _bash_ enthält ein Problem da ich ja Wort Zerlegung hätte - nein?)

Code: Alles auswählen

max@pc1:~$ var=`basename $0`;echo $var
bash
max@pc1:~$
oder auch

Code: Alles auswählen

max@pc1:~$ var="`basename $0`";echo $var
bash
max@pc1:~$
1) Sind meine Überlegungen richtig - stimmt die Reihenfolge?
2) gibt es eine möglichkeit mir Schritt für Schritt das alles anzeigen zu lassen - evtl. sowas wie man es von Debbugern beim programmieren kennt

TIA markus

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 15.02.2006 21:19:13

Hi meandtshell

Viel kann ich dazu nicht beitragen, ich habe nur einen kleinen Fehler in deiner Erklärung entdeckt:
meandtshell hat geschrieben:

Code: Alles auswählen

jetzt erfolgt die Kommando Substitution 
prog="`basename "bash"`" 
wird hier zu 
prog=""bash""
Bei der Kommando Substitution wird

Code: Alles auswählen

basename "bash"
durch ersetzt und nicht durch

Code: Alles auswählen

"bash"
. Daher kommt

Code: Alles auswählen

prog="bash"
raus und nicht

Code: Alles auswählen

prog=""bash""
vielleicht kann ich aber noch etwas zur Verwirrung beitragen :):

Obwohl normalerweise hier eine "Wortezerlegung" stattfindet:

Code: Alles auswählen

gms@gms1:~$ var=a b; echo $var
bash: b: command not found
Wird hier die Ausgabe von "basename" nicht mehr einer Wortezerlegung unterzogen (die äußeren Hochkomma werden nicht benötigt):

Code: Alles auswählen

X="prefix postfix"
var=`basename "$X"`;echo $var
var="`basename "$X""`;echo $var
Hier werden sie aber benötigt:

Code: Alles auswählen

#!/bin/sh
for i in "`basename "$0"`"; do
echo $i
done
lg
gms

Benutzeravatar
meandtheshell
Beiträge: 4054
Registriert: 14.01.2005 17:51:30

Beitrag von meandtheshell » 16.02.2006 10:44:35

hallo gms

hm ... ist schon seltsam den bei mir sieht das so aus

Code: Alles auswählen

markusgattol@pc1:~$ basename \"$0\"
"bash"
markusgattol@pc1:~$ echo `basename \"$0\"`
"bash"
markusgattol@pc1:~$
d.h. ich habe dann schon

Code: Alles auswählen

var=""bash""
(das quote removal räumt dann denke ich alle vier Hochkommas weg - nein?)und nicht nur

Code: Alles auswählen

var="bash"
Wie gesagt eine Möglichkeit sich das Schritt für Schritt anzeigen zu lassen wäre super++

markus (still walking in circles here) :roll:

Benutzeravatar
godsmacker
Beiträge: 902
Registriert: 16.03.2003 21:50:26
Lizenz eigener Beiträge: Artistic Lizenz
Wohnort: Chemnitz
Kontaktdaten:

Beitrag von godsmacker » 16.02.2006 12:47:54

zsh kann das (in gewissem Masse. Ich weiss nicht, ob sie wirklich alle oben genannten Schritte unterscheidet).

-Flo

Benutzeravatar
meandtheshell
Beiträge: 4054
Registriert: 14.01.2005 17:51:30

Beitrag von meandtheshell » 16.02.2006 13:59:12

godsmacker hat geschrieben:zsh kann das (in gewissem Masse. Ich weiss nicht, ob sie wirklich alle oben genannten Schritte unterscheidet).
hallo - danke für den hint

Ich werde mich nicht "außerhalb" der bash schlau machen, da:
- ich ausschließlich die bash verwende
- das nur noch mehr Verwirrung bringen würde

Gründe warum ich die bash verwende:
- sie ist die offizielle GNU shell
- AFAICT die "mächtigste" shell die ich kenne

Dennoch danke für deinen Hinweiß :D
Der Thread zeigt eigentlich nur schön das man auch nach langer Zeit immer wieder ganz leicht planlos dastehen kann aufgrund der immens großen Möglichkeiten die ein Tool, Interface etc. bietet.
Ein Verhalten, dass ich bis heute eigenlich nur von emacs kannte - möglicherweiße komme ich in ein paar Jahren drauf das Fluge zum Mond mit dem emacs möglich sind.

zurück zum Thema (folgende Zeilen ergeben alle \z):

Code: Alles auswählen

echo \\z
echo "\z"
echo "\\z"
echo `echo "\z"`
echo `echo "\\z"`
echo `echo \\\z`      
echo `echo \\\\z`     
echo `echo \\\\\\z` 
Ich schreibe mir nun auf die Brust das die Erklärung dafür ist, dass am Ende der Expansions Kette duch qoute removal alle Ausdrücke \z ergeben.

Dennoch - jener der mir eine Möglichkeit nennt sich Schrittweise von/mit der bash anzeigen zu lassen was passiert der bekommt einen Kuß (natürlich nur metaphorisch gesehen) :mrgreen:

markus (reached that point, where walking in circles sucks ...)

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 16.02.2006 17:50:10

In diesen beiden Fällen, bekommt das Programm "basename" als erstes Argument den Wert "bash" ohne die Hochkomma

Code: Alles auswählen

gms@gms4:~$ basename $0
bash
gms@gms4:~$ basename "$0"
bash
In diesem Fall, hast du die Hochkomma escapet, daher werden diese von der Bash nicht entfernt. Das Programm "basename" bekommt hier also als erstes Argument den Wert "bash" mit den Hochkomma.

Code: Alles auswählen

gms@gms4:~$ basename \"$0\"
"bash"
Gruß
gms
Zuletzt geändert von gms am 13.05.2007 00:03:37, insgesamt 1-mal geändert.

Benutzeravatar
meandtheshell
Beiträge: 4054
Registriert: 14.01.2005 17:51:30

Beitrag von meandtheshell » 16.02.2006 18:43:55

hallo gms

das was du gerade skizziert hast ist absolut ok - das wusste ich wohl ...

klar war mir nicht ganz bzw. konnte ich als ich den Thread gestarted hatte nicht 100%ig nachvollziehen warum hier 2xdouble qoutes vorkommen

Code: Alles auswählen

 
prog="`basename \"$0\"`"
Wie ich oben sagte ist es so das zum Schluß vier quotes über sind die dann alle im letzten Schritt der Expansions Kette duch quote removal gelöscht werden
aus

Code: Alles auswählen

var=""bash""
wird

Code: Alles auswählen

var=bash
daraus folgt

Code: Alles auswählen

echo $var
liefert

Code: Alles auswählen

markusgattol@pc1:~$ var="`basename \"$0\"`"; echo $var
bash
markusgattol@pc1:~$
Bei der Variante ohne äußere double quotes bleiben die inneren double quotes zunächst erhalten, da sie ja escaped wurden - also wird wie du gesagt hast "bash" als argument an basename übergeben.

basename macht aus "bash" nichts bzw. verändert nichts da kein Pfad vorhanden ist den basename entfernen könnte. "bash" wandert also weiter und wird der Variablen zugewiesen.

Code: Alles auswählen

markusgattol@pc1:~$ var=`basename \"$0\"`; echo $var
"bash"
markusgattol@pc1:~$
Bei der Variante mit äußeren quotes erfolgt (IMHO) zweimal ein quote removal
- das erste lässt die backslashes verschwinden nachdem die Variable $0 expandiert ist
- das zweite qoute removal findet unmittelbar vor der Zuweisung zur Variable statt also hier var=""bash""


markus

Antworten