COMMENCER et FIN avec la commande awk

13

Selon le manuel de awk, BEGIN et END ne sont pas utilisés pour faire correspondre l'entrée, mais plutôt pour fournir des informations de démarrage et de nettoyage au script awk. Voici l'exemple donné:

ls -l | \
awk 'BEGIN { print "Files found:\n" } /\<[a|x].*\.conf$/ { print $9 }'
Files found:
amd.conf
antivir.conf
xcdroast.conf
xinetd.conf

Tout d'abord, cela imprime une chaîne à afficher. Ensuite, il vérifie l'entrée pour une correspondance de modèle, où l'entrée commence par un ou x suivi par un caractère une ou plusieurs fois suivi du .conf. Pour toutes les correspondances, la 9e colonne est imprimée.

Le fait que nous sommes obligés d'utiliser commence ici, cela signifie-t-il que awk ne peut utiliser au plus qu'une fonction d'impression qui contient un début ou une fin? Sinon, pourquoi ne pouvons-nous pas simplement utiliser la fonction d'impression au début sans le mot-clé BEGIN? Il semble que le BEGIN soit superflu.

JohnMerlino
la source
Une simple exécution de la commande sans BEGIN répondrait à votre question, montrant qu'elle n'est pas superflue et que vous obtiendriez un résultat différent.
msb

Réponses:

11

Ce BEGINn'est pas superflu. Si vous ne spécifiez pas, BEGINle printserait exécuté pour chaque ligne d'entrée.

Citant du manuel :

Une BEGINrègle n'est exécutée qu'une seule fois, avant la lecture du premier enregistrement d'entrée. De même, une ENDrègle est exécutée une seule fois, une fois toutes les entrées lues.

$ seq 5 | awk 'BEGIN{print "Hello"}/4/{print}'   # Hello printed once
Hello
4
$ seq 5 | awk '{print "Hello"}/4/{print}'        # Hello printed for each line of input
Hello
Hello
Hello
Hello
4
Hello
$
devnull
la source
7

awktraite chaque ligne d'entrée pour les expressions données dans le corps autre que BEGINet ENDblocs. Dans le cas de BEGINet de ENDblocs, awkne traitera les instructions qu'une seule fois, avant le début du traitement de l'entrée et après le traitement de l'entrée. Sans le BEGINbloc, non seulement vous ne seriez pas en mesure d'imprimer des informations ponctuelles telles que des en-têtes, mais vous ne seriez pas en mesure d'initialiser efficacement certaines des variables requises par le corps. De plus, Pour votre information, un awkprogramme peut avoir plusieurs BEGINet ENDblocs.

mkc
la source
2

awkexécute chaque bloc uniquement lorsque le modèle avant sa correspondance. Un motif vide (juste un bloc) correspond à chaque ligne. BEGINet ENDsont des motifs spéciaux qui correspondent au début et à la fin du fichier (analogues à la signification de ^et $dans le sens horizontal).

Si vous souhaitez exécuter quelque chose avant de lire le fichier, utilisez BEGIN. Par exemple, l'initialisation de compteurs ou quelque chose. ENDpourrait ensuite recueillir les résultats.

orion
la source
0

Dans l'exemple donné, qui je pense est simplifié par souci de clarté pédagogique, vous avez raison de dire qu'il est superflu. Vous pouvez obtenir les mêmes résultats sans utiliser BEGIN.

1 == NR            { print "Files found:\n" }
/\<[a|x].*\.conf$/ { print $9               }

produirait les mêmes résultats puisque l'instruction print est limitée à la première ligne d'entrée uniquement.

Cela étant dit, les blocs BEGINet ENDsont des outils incroyablement puissants. Comme d'autres solutions l'ont mentionné, vous pouvez utiliser le BEGINbloc pour initialiser des variables ou d'autres routines qui ne doivent être exécutées qu'une seule fois, mais il peut également être utilisé pour exécuter des commandes Awk lorsqu'il n'y a aucun fichier à traiter. Un exemple simple:

BEGIN { print sqrt(12/4) }

Vous pouvez voir un exemple plus sérieux de programmation dans Awk sans traiter aucune entrée ici .

De même, le ENDbloc est extrêmement utile pour effectuer des calculs et résumer toutes les entrées. Cela ne peut pas être fait (généralement) sans première lecture de toutes les données. Un exemple simple de résumé des contributions peut être trouvé ici

myq
la source