Gibt es zwei Möglichkeiten, awk vars über die Kommandozeile einzustellen?

10

Ich bemerkte ein O'Reilly- awkBeispiel (1997), das eine awk-Variable zuordnete, indem sie in der Befehlszeile nach dem Programmtext gesetzt wurde. Es funktioniert, aber ich kann diese Syntax nicht in man / info awk finden . Habe ich es gerade verpasst? ist es beraubt ...? Die einzige Syntax, die ich im Handbuch gesehen habe, ist die -vOption.

awk '/home/{print foo, bar}' foo="cat" bar="dog" /proc/$$/cmdline

Ausgabe: cat dog

Peter.O
quelle

Antworten:

11

Es ist tatsächlich in POSIX awk(Link zu POSIX 2008, frühere Versionen hatten es auch, glaube ich). -vwird im Abschnitt Optionen beschrieben , der andere Weg ist im Abschnitt Operanden .

Es gibt einen Unterschied zwischen -vund Übergeben der Zuweisungen am Ende mit den Dateinamen:

  • Mit -v:

Die Anwendung muss sicherstellen, dass das Zuweisungsargument dieselbe Form wie ein Zuweisungsoperand hat. Die angegebene Variablenzuweisung muss vor der Ausführung des awk-Programms erfolgen, einschließlich der mit BEGIN-Mustern verbundenen Aktionen (falls vorhanden). Diese Option kann mehrfach vorkommen.

  • Gemischt mit den Dateinamen:

[...] Jede solche Variablenzuweisung erfolgt gegebenenfalls unmittelbar vor der Verarbeitung der folgenden Datei . Daher muss eine Zuweisung vor dem ersten Dateiargument nach den BEGIN-Aktionen (falls vorhanden) ausgeführt werden, während eine Zuweisung nach dem letzten Dateiargument vor den END-Aktionen (falls vorhanden) erfolgen soll. Wenn keine Dateiargumente vorhanden sind, müssen Zuweisungen vor der Verarbeitung der Standardeingabe ausgeführt werden.

Beispiel:

$ cat input 
hello
hello
$ awk -v var=one 'BEGIN{print var} /hello/{print var} END{print var}' \
    var=two input var=three input var=four
one
two
two
three
three
four
Matte
quelle
Beeindruckend! Das fügt einige interessante Kontrollpunkte hinzu ... es wird sich als nützlich erweisen. Danke ...
Peter.O
1
Mein erstes "Wow!" hält immer noch, aber es wurde etwas gemildert, indem man sich Arceges Antwort genauer ansah ... Ich habe es mit einer realen Datei namens "var = drei" getestet ... hatte awkVorrang vor einer variablen Zuweisung ... Dies hat eine wichtige Konsequenz dh. In allen Fällen, in denen ein Dateiname diese Form hat, wird er ignoriert und die Variable wird festgelegt. Es scheint, dass die einzige Möglichkeit, diesen Konflikt zu vermeiden, darin besteht, sicherzustellen, dass Dateinamen für das aktuelle Arbeitsverzeichnis immer vorangestellt werden müssen mit ihrem relativen Weg:./var=three
Peter.O
@ Peter.O, ja, das ist auch einer der Gründe, warum die -vSyntax eingeführt wurde. Sie sollten sich die -vSyntax als die bevorzugte Methode für zukünftige Aufgaben vorstellen.
Dubiousjim
@ Peter.O, ausgezeichneter Punkt über das "Gotcha", wenn ein Dateiname eine gültige Variablenzuweisung ist. Wenn Sie eine Shell-Variable verwenden, die einen Dateinamen enthält, und diesen als Argument übergeben, awkkönnen Sie den folgenden Haken verwenden:[ "$myfile" == "${myfile#/}" ] && myfile="./$myfile"
Wildcard
4

Dies ist eine alte Art, Variablen extern in zu setzen awk. Es war mehrdeutig (was wäre, wenn Sie einen Dateinamen hätten foo=cat), daher fügten spätere Versionen eine -vOption hinzu . Es sollte wahrscheinlich aus Gründen der Abwärtskompatibilität funktionieren, aber Sie können nicht garantieren. Und wie gesagt, die -vOption ist neuer, sodass awkmöglicherweise nicht alle Versionen von sie unterstützen.

Arcege
quelle
Ihr Kommentar zur Möglichkeit eines Zusammenstoßes von Dateinamen ist gut ... Ich habe ihn getestet und er ist definitiv ein Problem. Ich habe ein bisschen mehr darüber in einem Kommentar zu Mats Antwort geschrieben. Danke, dass Sie dieses Problem hervorgehoben haben (+1)
Peter.O
2
Wie in [Mat s answer](http://unix.stackexchange.com/a/34258/9537), -v` und der Argumentzuweisung erläutert, unterscheiden sie sich tatsächlich darin, wann sie wirksam werden. Ist auch -vin POSIX und sollte in allen außer den ältesten awkImplementierungen vorhanden sein. Die Verwendung ./oder Sicherstellung, dass der Dateiname ein Nicht-Identifizierungszeichen enthält, ist wahrscheinlich die zuverlässigste Methode zur Unterscheidung.
jw013