Utiliser une variable shell dans awk

8

Voici mon script (pour trouver les fichiers qui contiennent un modèle spécifié):

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

Je voudrais utiliser mon script avec un argument §:

MyScript.sh pattern

Mon problème est que je n'arrive pas à insérer la $1variable awk.

Quand j'essaie de déboguer mon script

bash -x MyScript.sh pattern

Voici la sortie:

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

La $vawkvariable semble vide.

Une idée?

Nicolas
la source

Réponses:

7

Vous semblez confondre les variables awk et les variables shell. awk -v vawk="$1"crée une variable awk appelée vawk, mais vous essayez d'utiliser la syntaxe shell ( $vawk). Cela ne fonctionne pas car le shell n'a pas de variable appelée vawk. Je pense que ce que tu veux c'est

awk -v vawk="$1" '$0 ~ vawk { c++ } # ...'
#                      ^ awk variable syntax
jw013
la source
1
Notez que awkdéveloppe les séquences d'échappement de type C dans $1, de sorte que cette approche ne fonctionne pas si elle $1peut contenir des barres obliques inverses (courantes pour les expressions rationnelles). Vous pouvez utiliser le ENVIRONtableau spécial awk à la place.
Stéphane Chazelas
6

Reproduit de cela maintenant fermé en double question car il comprend des avertissements sur les limites de passage variable awk que l' on pourrait trouver utile.

Une variable shell n'est que cela: une variable shell . Si vous voulez le transformer en une variable awk , vous avez besoin d'une syntaxe telle que:

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

ou

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

Cependant, ceux-ci souffrent d'un problème: les séquences d'échappement y sont développées (et avec GNU awk4.2 ou supérieur, si elles $xcommencent @/et se terminent /, elles sont traitées comme une variable de type regexp ).

Ainsi, par exemple, si la variable shell contient les deux caractères barre oblique inverse et n , la variable awk finira par contenir le caractère de nouvelle ligne (et avec gawk 4.2+, si elle contient @/foo/, la variable awk contiendra fooet sera de type regexp).

Une autre approche (mais qui, comme pour, -vnécessite un awk ou un nawk POSIX (par opposition à l'awk des années 1970 toujours trouvé comme /bin/awkdans Solaris)) consiste à utiliser des variables d'environnement:

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

Une autre approche (toujours avec des awks plus récents) consiste à utiliser le tableau ARGV dans awk:

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