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
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
|
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
|
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) |
{
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.
|