Verwenden Sie eine Shell-Variable in awk

8

Hier ist mein Skript (um die Dateien zu finden, die ein bestimmtes Muster enthalten):

find . -type f \
    -exec awk -v vawk="$1" '/'"$vawk"'/ {c++} c>0 { print ARGV[1]; exit 0 } END { if (! c) {exit 1}}' \{\} \;

Ich möchte mein Skript mit einem Argument verwenden §:

MyScript.sh pattern

Mein Problem ist, dass ich es nicht schaffe, die $1Variable einzufügen awk.

Wenn ich versuche, mein Skript zu debuggen

bash -x MyScript.sh pattern

Hier ist die Ausgabe:

+ find . -type f -exec awk -v vawk=pattern '// {c++} c>0 {print ARGV[1] ; exit 0 } END { if (! c) {exit 1}}' '{}' ';'

Die $vawkVariable scheint leer zu sein.

Irgendeine Idee?

Nicolas
quelle

Antworten:

7

Sie scheinen awk-Variablen und Shell-Variablen zu verwechseln. awk -v vawk="$1"Erstellt eine awk- Variable mit dem Namen vawk, Sie versuchen jedoch, die Shell- Syntax ( $vawk) zu verwenden. Dies funktioniert nicht, da in der Shell keine Variable aufgerufen wird vawk. Ich denke was du willst ist

awk -v vawk="$1" '$0 ~ vawk { c++ } # ...'
#                      ^ awk variable syntax
jw013
quelle
1
Beachten Sie, dass awkdie C-ähnlichen Escape-Sequenzen in erweitert werden $1, sodass dieser Ansatz nicht funktioniert, wenn er $1möglicherweise Backslash-Zeichen enthält (häufig für reguläre Ausdrücke). Sie können ENVIRONstattdessen das awk-Spezialarray verwenden.
Stéphane Chazelas
6

Wiedergabe aus dieser nun abgeschlossenen doppelten Frage, da sie Warnungen zu den Einschränkungen der Übergabe von awk-Variablen enthält, die möglicherweise nützlich sind.

Eine Shell-Variable ist genau das: eine Shell- Variable . Wenn Sie daraus eine awk- Variable machen möchten , benötigen Sie eine Syntax wie:

awk -v x="$x" '$2 == x {print $1}' infile

oder

awk '$2 == x {print $1}' x="$x" infile

Diese haben jedoch ein Problem: Escape-Sequenzen werden in ihnen erweitert (und mit GNU awk4.2 oder höher wird es als regulärer Variablentyp behandelt , wenn es mit $xbeginnt @/und endet/ .

Wenn die Shell-Variable beispielsweise die beiden Zeichen Backslash und n enthält , enthält die awk-Variable am Ende das Zeilenumbruchzeichen (und bei gawk 4.2+ enthält @/foo/die awk-Variable , sofern sie enthält , den fooTyp und ist vom Typ regexp).

Ein anderer Ansatz (der jedoch -vein POSIX awk oder nawk erfordert (im Gegensatz zu dem /bin/awkin Solaris noch in den 1970er Jahren gefundenen awk )) ist die Verwendung von Umgebungsvariablen:

x="$x" awk '$2 == ENVIRON["x"] {print $1}' infile

Ein anderer Ansatz (immer noch mit neueren awks) ist die Verwendung des ARGV-Arrays in awk:

awk 'BEGIN {x = ARGV[1]; delete ARGV[1]}
  $2 == x {print $1}' "$x" infile
Stéphane Chazelas
quelle