Gentoo Logo

Avertissement : La version originale de cet article a été publiée sur IBM developerWorks et est la propriété de Westtech Information Services. Ce document est une traduction de la mise à jour de la version originale de l'article réalisée par l'équipe de documentation Gentoo et contient quelques améliorations proposées par l'équipe de documentation de Gentoo Linux.
Ce document n'est pas activement maintenu.


Awk par l'exemple, 1re partie

Table des matières :

1.  Une introduction au grand langage au nom étrange

Pour la défense d'Awk

Dans cette série d'articles, je vais vous aider à devenir un codeur Awk compétent. Je l'admets, Awk n'a un nom ni très élégant, ni « cool », et la version GNU d'Awk, appelée gawk, a un nom complètement surnaturel. Ceux qui ne sont pas familiers avec ce langage peuvent entendre « awk » et penser à un langage compliqué et archaïque, capable de conduire le gourou Unix le plus compétent au bord de la folie !

D'accord, Awk n'a pas un grand nom. Mais c'est un grand langage. Awk est destiné au traitement de texte et à la génération de rapports, bien qu'il présente de nombreuses fonctionnalités bien conçues pour programmer sérieusement. Et à la différence de quelques langages, Awk a une syntaxe familière et emprunte certaines des meilleures parties des langages tels que le C, Python et Bash (bien que techniquement, Awk ait été créé avant Python et Bash). Awk est l'un de ces langages qui, une fois appris, deviendra un outil majeur de vos stratégies de développement.

Le premier awk

Exemple de code 1.1 : Le premier awk

$ awk '{ print }' /etc/passwd

Vous devez voir le contenu de votre fichier /etc/passwd apparaître devant vos yeux. Maintenant, une explication de ce qu'awk fait. Quand nous avons lancé awk, nous avons spécifié /etc/passwd comme fichier en entrée. Quand nous avons exécuté awk, il a traité la commande print pour chaque ligne de /etc/passwd, dans l'ordre. Tous les résultats ont été envoyés vers stdout et nous obtenons un résultat identique à cat /etc/passwd.

Maintenant, une explication du bloc de code { print }. Dans awk, les accolades sont utilisées pour grouper des blocs de code ensemble, comme en C. À l'intérieur de notre bloc de code, nous avons une simple commande « print ». Dans awk, quand une commande « print » apparaît seule, le contenu complet de la ligne courante est affiché.

Exemple de code 1.2 : Afficher la ligne courante

$ awk '{ print $0 }' /etc/passwd
$ awk '{ print "" }' /etc/passwd

Dans awk, la variable $0 représente la ligne courante entière, donc « print » et « print $0 » donnent exactement la même chose.

Exemple de code 1.3 : Remplir l'écran avec du texte

$ awk '{ print "hiya" }' /etc/passwd

Plusieurs champs

Exemple de code 1.4 : print $1

$ awk -F":" '{ print $1 $3 }' /etc/passwd
halt7
operator11
root0
shutdown6
sync5
bin1
etc.

Exemple de code 1.5 : print $1 $3

$ awk -F":" '{ print $1 " " $3 }' /etc/passwd

Exemple de code 1.6 : $1$3

$ awk -F":" '{ print "username: " $1 "\t\tuid:" $3 }' /etc/passwd
username: halt          uid:7
username: operator      uid:11
username: root          uid:0
username: shutdown      uid:6
username: sync          uid:5
username: bin           uid:1
etc.

Les scripts externes

Exemple de code 1.7 : Exemple de script

BEGIN { FS=":" }
{ print $1 }

La différence entre ces deux méthodes est la façon dont nous avons précisé le séparateur de champs « : ». Dans ce script, le séparateur de champs est spécifié à l'intérieur même du code (en renseignant la variable FS « Field Separator »), alors que notre exemple précédent renseigne la variable FS en utilisant l'option -F":" d'awk sur la ligne de commande. Il est en général plus judicieux de renseigner le séparateur de champs à l'intérieur du script même, simplement parce que vous avez ainsi un argument en ligne de commande en moins à vous rappeler de taper. Nous aborderons la variable FS plus en détail, ultérieurement dans cet article.

Les blocs BEGIN et END

Normalement, awk exécute chaque bloc du code de votre script une fois pour chaque ligne en entrée. Cependant, dans de nombreuses situations en programmation, vous pouvez avoir besoin d'exécuter du code d'initialisation avant qu'awk ne commence à traiter le texte à partir du fichier en entrée. Pour ces situations, awk permet de définir un bloc BEGIN. Nous avons utilisé un bloc BEGIN dans l'exemple précédent. Parce que le bloc BEGIN est évalué avant qu'awk ne commence à traiter le fichier d'entrée, c'est le meilleur endroit pour initialiser la variable FS (séparateur de champs), afficher un en-tête, ou initialiser d'autres variables globales que vous réutiliserez plus tard dans le programme.

Awk fournit aussi un autre bloc spécial, appelé le bloc END. Awk exécute ce bloc après que toutes les lignes du fichier d'entrée aient été traitées. Généralement, le bloc END est utilisé pour réaliser des calculs finaux ou pour afficher des résumés qui doivent apparaître à la fin du flux de sortie.

Expressions rationnelles et blocs

Exemple de code 1.8 : Expressions rationnelles et blocs

/foo/ { print }
/[0-9]+\.[0-9]*/ { print }

Expressions et blocs

Exemple de code 1.9 : fredprint

$1 == "fred" { print $3 }

Exemple de code 1.10 : root

$5 ~ /root/ { print $3 }

Tests conditionnels

Exemple de code 1.11 : if

{ 
    if ( $5 ~ /root/ ) { 
        print $3 
    }
}

Les deux scripts fonctionnent de la même façon. Dans le premier exemple, l'expression booléenne est placée en dehors du bloc, alors que dans le second exemple, le bloc est exécuté pour chaque ligne en entrée et nous avons sélectivement réalisé la commande « print » en utilisant un test « if ». Les deux méthodes sont valables et vous pouvez choisir celle qui est le plus en adéquation avec les autres parties de votre script.

Exemple de code 1.12 : if if

{
    if ( $1 == "foo" ) {
        if ( $2 == "foo" ) {
            print "uno"
        } else {
            print "one"
        }
    } else if ($1 == "bar" ) {
        print "two"
    } else {
        print "three"
    }
}

Exemple de code 1.13 : if

! /matchme/ { print $1 $3 $4 }

Exemple de code 1.14 : if

{
    if ( $0 !~ /matchme/ ) {
        print $1 $3 $4
    }
}

Les deux scripts n'affichent que les lignes ne contenant pas une séquence de de caractères qui corresponde à « matchme ». Ici encore, vous pouvez choisir la méthode qui convient le mieux pour votre code. Les deux scripts font la même chose :

Exemple de code 1.15 : Afficher les champs correspondant à foo et à bar

( $1 == "foo" ) && ( $2 == "bar" ) { print } 

Cet exemple affiche seulement les lignes dont le premier champ vaut « foo » et dont le deuxième champ vaut « bar ».

Variables numériques !

Dans le bloc BEGIN, nous initialiserions une variable x à zéro. Alors, chaque fois qu'awk rencontrerait une ligne vide, il exécuterait x=x+1, incrémentant x. Après que toutes les lignes aient été traitées, le bloc END serait exécuté et awk afficherait un résumé final spécifiant le nombre de lignes vides trouvées.

Variables avec des caractères

Exemple de code 1.16 : Exemple

2.01

Exemple de code 1.17 : 1.01x$( )1.01

{ print ($1^2)+1 }

Si vous expérimentez un peu, vous verrez que si une variable ne contient pas un nombre valide, awk traitera cette variable comme un zéro numérique quand il évaluera votre expression mathématique.

Plein d'opérateurs

Une autre chose intéressante d'awk est son complément d'opérateurs mathématiques. En plus de l'addition, soustraction, multiplication et division, awk nous permet d'utiliser l'opérateur exposant « ^ » utilisé précédemmment, l'opérateur modulo « % » (reste de division) et d'autres opérateurs empruntés au C.

Cela inclut la pré et la post-incrémentation/decrémentation (i++, --foo), des opérateurs d'assignation add/sub/mult/div (a+=3, b*=2, c/=2.2, d-=6.2). Mais ce n'est pas tout : nous avons aussi les opérateurs d'assignation modulo/exposant (a^=2, b%=4).

Les séparateurs de champs

Awk a son propre complément de variables spéciales. Certaines d'entre elles vous permettent de bien peaufiner vos fonctions awk, alors que d'autres peuvent être utilisées pour récupérer de l'information pertinente sur les données en entrée. Nous avons déjà abordé une de ces variables spéciales, FS. Comme mentionné précédemment, cette variable vous permet de préciser une séquence de caractères qu'awk vise à trouver entre les champs. Quand nous utilisions /etc/passwd en entrée, FS était à « : ». Bien qu'il ait fait son travail, FS nous permet encore plus de flexibilité.

Exemple de code 1.18 : Un autre séparateur de champ

FS="\t+"

Ci-dessus, nous utilisons le caractère spécial d'expression rationnelle « + », qui signifie « une ou plusieurs occurrences du caractère précédent ».

Exemple de code 1.19 : Mettre une espace comme FS

FS="[[:space:]+]"

Bien que cet assignement fasse son travail, il n'est pas nécessaire. Pourquoi ? Parce que, par défaut, FS correspond à un simple caractère d'espacement qu'awk interprète comme « une ou plusieurs espaces ou tabulations ». Dans cet exemple particulier, le paramètre par défaut de FS est exactement ce que nous recherchions !

Exemple de code 1.20 : Exemple de séparateur de champ

FS="foo[0-9][0-9][0-9]"

Nombre de champs

Exemple de code 1.21 : Nombre de champs

{
    if ( NF > 2 ) {
        print $1 " " $2 ":" $3 
    }
}

Nombre d'enregistrements

Exemple de code 1.22 : Nombre d'enregistrements NR (Number of Records)

{
    # Nous ne voulons pas afficher l'en-tête
    if ( NR > 10 ) {
        print "ok, now for the real information!"
    }
}

Awk fournit des variables supplémentaires qui peuvent être utilisées dans une variété de situations. Nous aborderons la plupart de ces variables dans les prochains articles.

Nous en sommes à la fin de notre première exploration d'Awk. Dans la suite de cette série, je décrirai des fonctionnalités plus avancées d'Awk et nous finirons la série avec une application Awk dans le monde réel. Dans le même temps, si vous êtes désireux d'en apprendre plus, consultez les ressources listées ci-dessous.

2.  Ressources

Liens utiles

  • Lisez les autres articles de Daniel sur Awk publiés sur developerWorks : Common threads: Awk by example, Partie 2.
  • Si vous recherchez un bon vieux livre, O'Reilly's sed & awk, 2nd Edition est un très bon choix.
  • Consultez aussi la FAQ comp.lang.awk. Elle contient de nombreux liens supplémentaires sur Awk.
  • Awk tutorial de Patrick Hartigan est présenté avec des scripts awk avancés.
  • Thompson's TAWK Compiler compile des scripts awk en exécutables binaires rapides. Des versions sont disponibles pour Windows, OS/2, DOS et UNIX.
  • The GNU Awk User's Guide est disponible comme référence en ligne.


Imprimer

Dernière mise à jour le 8 janvier 2008

Résumé : Awk est un langage très intéressant avec un nom étrange. Dans ce premier article d'une série en 3 parties, Daniel Robbins va rapidement améliorer votre niveau en programmation Awk. Au fur et à mesure que nous progresserons, des sujets plus avancés seront abordés, avec en conclusion une démonstration avancée d'une application Awk dans le monde réel.

Daniel Robbins
Auteur

Christophe Lefebvre
Traducteur

Donate to support our development efforts.

Copyright 2001-2014 Gentoo Foundation, Inc. Questions, Comments? Contact us.