On Die, 06 Mai 2003 at 01:47 (+0200), Thomas Michalka wrote:
Jan Trippler schrieb: [...]
jan@k500:~> echo pos1 pos2 pos3 | awk ' { print $pos } ' pos=2 pos2 [...] Aber was in diesem Beispiel von Dir definitiv nicht der Fall sein kann, ist, daß hier eine Shell-Variable an awk übergeben wird, weil $pos hier gar nicht ausgewertet wird. Allerdings hast Du Dich hier wohl nur verschrieben, weil Du das durch Deine Beispiele mit dem in der bash freien $pos nachher selber widerlegst.
Ja, die Finger waren schneller als das Auge ;-) Ich meinte es so: pos=2 echo pos1 pos2 pos3 | awk ' { print $pos } ' pos=$pos [...]
Es gibt einen Unterschied zwischen der awk-Variablen pos und der Shell-Variablen $pos, der letzte print zeigt das. Deshalb findet hier schon eine Parameter-Übergabe statt, es wird ja innerhalb des awk mit der awk- und nicht der Shell-Variablen gearbeitet. Das ist der Unterschied zur $'$pos' Variante, bei der ja praktisch der Teil '$pos' sich ausserhalb des awk befindet und durch die Shell ausgewertet wird.
Das gilt sowohl für $'$pos' als auch für '$pos', weil in *beiden* Fällen das $pos in der Kommandozeile für die bash ungeschützt zur Auswertung bereitsteht. Das erste $ in $'$pos' steht ja innerhalb des ersten Hochkomma-Paars (das Beispiel ist hier leider nicht mehr sichtbar) und wird deshalb erst von awk interpretiert.
Die Stellen meinte ich auch nicht. Logischerweise sind diese beiden Konstrukte Shell-Variablen, sie befinden sich ausserhalb des schützenden ''-Quotings und werden deshalb von der Shell _vor_ dem Start des awk substituiert. Wie Du weiter hinten richtig geschrieben hast, kriegt hier der awk nur $2 bzw. 2 zu sehen.
Nun möchte ich aber begründen, warum hier für mich - formal gesehen - *keine Parameterübergabe* stattfindet. Allerdings wird es jetzt kompliziert für mich den logischen Sachverhalt sprachlich korrekt auszudrücken. Aber ich will es versuchen ...
Doch, das ist eine astreine Parameter-Übergabe, Du bist nur an der falschen Stelle (den print habe ich nur eingebaut, um die Unterschiede zu verdeutlichen). Nochmal die Readers-Digest-Version (mit eindeutigen Variablennamen): shellpos=2 echo erstes_argument zweites_argument drittes_argument | \ awk ' { print "Auswertung von $shellpos = '$shellpos'", "; Argument = ", $'$shellpos'; print "und nun awkpos = ", awkpos, "; Argument = ", $awkpos; awkpos --; print "der Beweis = ", awkpos, "; Argument = ", $awkpos; } ' awkpos=$shellpos ^^^^^^^^^^^^^^^^ das hier ist die Parameter-Übergabe
Der Unterschied zwischen der awk-Variablen pos und der bash-Variablen pos besteht darin, daß erstere erst belegt (pos=2 am Schluß) wird, nachdem awk gestartet wurde, während die bash schon bei der Interpretation der Kommandozeile das Konstrukt $pos durch den Textinhalt der letzteren ersetzt, d.h. $pos wird durch eine 2 ersetzt, wenn pos=2 in der bash vorher gesetzt wurde (kleine Verwirrung wirklich _nur_ wegen der Namensgleichheit der Variablen).
Zum Beginn des awk-Laufs gibt es also schon kein $pos mehr, awk sieht nur noch eine simple 2, und print 2 in awk ergibt nun mal ...
ACK
Es wird also in diesem Beispiel innerhalb des awk - zumindest an dieser Stelle - überhaupt nicht mit einer Variablen gearbeitet, sondern mit einer (Text-)Konstante.
Da diese, wie schon ausgeführt, durch Textersatz der bash eingeführt wurde, sehe ich hier keinesfalls eine Parameterübergabe, sondern so etwas wie den Textersatz im C-Präprozessor, eingeleitet durch ein #define.[1]
Ja, aus awk-Sicht stimmt das. Im obigen Beispiel wird der awk so gestartet: awk ' { print "Auswertung von $shellpos = 2", "; Argument = ", $2; print "und nun awkpos = ", awkpos, "; Argument = ", $awkpos; awkpos --; print "der Beweis = ", awkpos, "; Argument = ", $awkpos; } ' awkpos=2 Wie man hier auch schön sehen kann, wird in der 1. print-Anweisung der Ausdruck $shellpos _nicht_ ersetzt, er ist nämlich durch die ''-Quotes vor der Shell geschützt.
Als bekräftigendes Gegenbeispiel sei angeführt, daß awk durchaus Parameter übergeben bekommt, z.B. die Zuweisung pos=2 (!) am Schluß der Kommandozeile.
Und genau das meinte ich. [...]
Gerade ist mir noch ein besseres Beispiel eingefallen: jan@k500:~/tmp> pos=1 jan@k500:~/tmp> echo pos1 pos2 pos3 | awk ' { print $pos; pos=3; print $pos; print '$pos', pos; } ' pos=2 pos2 pos3 1 3
Das ist das Beispiel von oben, bloß daß Du vorher die bash-Variable pos mit dem Text "2" füllst.
Nein, ich setze die Shell-Variable auf 1, die _awk_Variable wird auf 2 gesetzt. Jan