web-dev-qa-db-fra.com

Comment faire correspondre un modèle donné dans une variable dans awk?

Je veux extraire une sous-chaîne où certains motifs existent à partir d'un fichier séparé du tuyau, donc j'ai utilisé la commande ci-dessous,

awk -F ":" '/REWARD REQ. SERVER HEADERS/{print $1, $2, $3, $4}' sample_profile.txt

Ici, 'REWARD REQ. SERVER HEADERS 'est un motif qui doit être recherché dans le fichier et imprimer ses 4 premières parties sur une ligne séparée par des deux-points.

Maintenant, je veux envoyer la variable bash pour agir comme un motif. J'ai donc utilisé la commande ci-dessous, mais cela ne fonctionne pas.

awk -v pat="$pattern" -F ":" '/pat/{print $1, $2 , $3, $4 } sample_profile.txt

Comment utiliser -v et -F dans une seule commande awk?

13
Chintamani Manjare

Le problème ici n’a pas à voir avec -F.

Le problème est l'utilisation de /pat/ lorsque vous souhaitez que pat soit une variable. Si vous dites /pat/, awk le comprend comme un "pat" littéral, il essaiera donc de faire correspondre les lignes contenant la chaîne "pat".

Si vous souhaitez fournir le modèle via une variable, vous devez utiliser ~ comme ceci:

 awk -v pat="$pattern" '$0 ~ pat'

Tous ensemble, votre code devrait être:

awk -v pat="$pattern" -F ":" '$0~pat{print $1, $2, $3, $4 }' file
#                             ^^^^^^

Voir un exemple:

Compte tenu de ce fichier:

$ cat file
hello
this is a var
hello bye

Cherchons des lignes contenant "hello":

$ awk '/hello/' file
hello
hello bye

Essayons maintenant de rechercher "pat", contenu dans une variable, comme vous le faisiez:

$ awk -v pat="hello" '/pat/' file
$                                    # NO MATCHES!

Utilisons maintenant l'expression $0 ~ pat:

$ awk -v pat="hello" '$0~pat' file
hello                                 # WE MATCH!
hello bye

Bien sûr, vous pouvez utiliser de telles expressions pour faire correspondre un seul champ et dire awk -v pat="$pattern" '$2 ~ pat' file et ainsi de suite.

De GNU Guide de l'utilisateur Awk → 3.1 Comment utiliser des expressions régulières :

Lorsqu'une expression rationnelle est entourée de barres obliques, telles que/foo /, nous l'appelons une constante d'expression rationnelle, un peu comme 5.27 est une constante numérique et "foo" est une constante de chaîne.

Et GNU Guide de l'utilisateur Awk → 3.6 Utiliser Dynamic Regexps :

Le côté droit d’un opérateur "~" ou "! ~" N’a pas besoin d’être une expression rationnelle constante (c'est-à-dire une chaîne de caractères entre des barres obliques). Ce peut être n'importe quel expression. L'expression est évaluée et convertie en une chaîne si nécessaire; le contenu de la chaîne est alors utilisé comme expression rationnelle. UNE l'expression rationnelle calculée de cette manière est appelée expression rationnelle dynamique ou .__ calculée. expression rationnelle:

BEGIN { digits_regexp = "[[:digit:]]+" }
$0 ~ digits_regexp    { print }

Cela définit digits_regexp comme une expression rationnelle décrivant un ou plusieurs chiffres, et teste si l'enregistrement d'entrée correspond à cette expression rationnelle.

26
fedorqui
awk -v pat="$pattern" -F":" '$0 ~ pat { print $1, $2, $3, $4 }' sample_profile.txt

Vous ne pouvez pas utiliser la variable dans la notation regex // (il n'y a aucun moyen de la distinguer de la recherche de pat); vous devez spécifier que la variable est une regex avec l'opérateur ~ (correspondant).

4
Jonathan Leffler

C'est un peu un bidouillage mais cela simplifie un peu les choses pour moi.

cmd="awk '/$pattern/'"
eval $cmd

en faire une chaîne vous permet d’abord de la manipuler au-delà des limites de awk

0
Ryan Donahoe