Vous n'êtes pas identifié(e).
L'icône rouge permet de télécharger chaque page du wiki visitée au format PDF et la grise au format ODT →
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente Prochaine révision Les deux révisions suivantes | ||
doc:programmation:awk [18/10/2012 05:33] smolski |
doc:programmation:awk [27/10/2013 18:21] smolski [awk] |
||
---|---|---|---|
Ligne 2: | Ligne 2: | ||
(//testé// - **smolski** 18/10/2012) Le retour sur le forum est ici : | (//testé// - **smolski** 18/10/2012) Le retour sur le forum est ici : | ||
- | * [[http://debian-facile.org/viewtopic.php?id=6057 | Lien vers le forum concernant ce tuto]] N'hésitez pas à y faire par de vos remarques, succès, améliorations ou échecs ! | + | * [[http://debian-facile.org/viewtopic.php?id=6057 | Lien vers le forum concernant ce tuto]] N'hésitez pas à y faire part de vos remarques, succès, améliorations ou échecs ! |
* Objet : awk | * Objet : awk | ||
* Niveau requis : AVISÉ | * Niveau requis : AVISÉ | ||
- | * Commentaires : // Cet utilitaire a été créé dans le but de remplacer les commandes [[commande:grep]] et [[commande:sed]]. // | + | * Commentaires : // Cet utilitaire a été créé dans le but de remplacer les commandes [[:doc:systeme:grep]] et [[:doc:systeme:sed]]. // |
* Débutant, à savoir : | * Débutant, à savoir : | ||
- | [[manuel:le_debianiste_qui_papillonne|Utiliser GNU/Linux en ligne de commande, tout commence là !.]] :-) | + | [[:doc:systeme:commandes:le_debianiste_qui_papillonne|Utiliser GNU/Linux en ligne de commande, tout commence là !.]] :-) |
+ | * Création par **smolski** 18/10/2012) | ||
+ | * Testé par **smolski** le 28/10/2013) | ||
+ | * Commentaires sur le forum : [[http://debian-facile.org/viewtopic.php?id=6057 | Lien vers le forum concernant ce tuto]]((N'hésitez pas à y faire part de vos remarques, succès, améliorations ou échecs !)) | ||
+ | |||
+ | === Nota === | ||
+ | |||
+ | Contributeurs, les FIXME sont là pour vous aider, supprimez-les une fois le problème corrigé ou le champ rempli ! | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | awk est un langage de programmation datant de 1977, date de son apparition dans le monde Unix. Il tire son nom des trois programmeurs qui l'ont développé : Alfred V. Aho, Peter J. Weinberger et Brian W. Kernighan. \\ | + | **awk** est un langage de programmation datant de 1977, date de son apparition dans le monde Unix. Il tire son nom des trois programmeurs qui l'ont développé : Alfred V. Aho, Peter J. Weinberger et Brian W. Kernighan. \\ |
Cet utilitaire a été créé dans le but de remplacer les commandes grep et sed. Sa grande souplesse lui a permis de connaître un succès immédiat. Et de nouvelles versions sont apparues au fil du temps : nawk et gawk aujourd'hui. | Cet utilitaire a été créé dans le but de remplacer les commandes grep et sed. Sa grande souplesse lui a permis de connaître un succès immédiat. Et de nouvelles versions sont apparues au fil du temps : nawk et gawk aujourd'hui. | ||
Ligne 18: | Ligne 25: | ||
===== Exercices ===== | ===== Exercices ===== | ||
- | Créez le fichier(([[commande:touch]])) file.txt ainsi : | + | Créez((Vous pouvez faire cela avec votre éditeur de texte favori, voire avec [[:doc:systeme:cat]] ou simplement en téléchargeant la liste.)) le fichier ''file.txt'' contenant la liste suivante : |
- | <code bash> | + | <code raw file.txt> |
- | touch file.txt</code> | + | |
- | + | ||
- | Et rédigez(([[commande:cat]])) dedans cette liste ainsi : | + | |
- | <code bash> | + | |
- | cat > file.txt <<EOS | + | |
Nom Genre Age | Nom Genre Age | ||
--------------------------------------- | --------------------------------------- | ||
Ligne 33: | Ligne 35: | ||
EMMA F 6 | EMMA F 6 | ||
THEO M 8 | THEO M 8 | ||
- | EOS</code> | + | </code> |
==== Extraire des colonnes ==== | ==== Extraire des colonnes ==== | ||
Extraire des données d'un fichier, par exemple les 2 premières colonnes : | Extraire des données d'un fichier, par exemple les 2 premières colonnes : | ||
- | <code bash> | + | <code user> |
- | awk '{ print $1, $2 }' file.txt | + | awk '{ print $1, $2 }' file.txt</code> |
+ | <code> | ||
Nom Genre | Nom Genre | ||
--------------------------------------- | --------------------------------------- | ||
Ligne 62: | Ligne 65: | ||
Retrouver les lignes qui contiennent CAMILLE : | Retrouver les lignes qui contiennent CAMILLE : | ||
- | <code bash> | + | <code user> |
- | awk '/CAMILLE/ { print $1, $3, $2 }' file.txt | + | awk '/CAMILLE/ { print $1, $3, $2 }' file.txt</code> |
+ | <code> | ||
CAMILLE 7 M</code> | CAMILLE 7 M</code> | ||
Ligne 70: | Ligne 74: | ||
Un autre filtre plus complexe, rechercher les lignes qui commencent par C et qui contiennent la lettre A ou la lettre O : | Un autre filtre plus complexe, rechercher les lignes qui commencent par C et qui contiennent la lettre A ou la lettre O : | ||
- | <code bash> | + | <code user> |
- | awk '/^C.*[AO]/ { print $1, $3, $2 }' file.txt | + | awk '/^C.*[AO]/ { print $1, $3, $2 }' file.txt</code> |
+ | <code> | ||
CAMILLE 7 M | CAMILLE 7 M | ||
CHLOE 12 F | CHLOE 12 F | ||
Ligne 78: | Ligne 83: | ||
awk est également très utile et puissant pour gérer des filtres sur des paragraphes. \\ | awk est également très utile et puissant pour gérer des filtres sur des paragraphes. \\ | ||
Pour récupérer les lignes de CL à E, tapez : | Pour récupérer les lignes de CL à E, tapez : | ||
- | <code bash> | + | <code user> |
- | awk '/^CL/,/^E/ { print $0 }' file.txt | + | awk '/^CL/,/^E/ { print $0 }' file.txt</code> |
+ | <code> | ||
CLARA F 11 | CLARA F 11 | ||
CLEMENT M 7 | CLEMENT M 7 | ||
Ligne 93: | Ligne 99: | ||
* NF : nombre de champs (nombre de colonnes). | * NF : nombre de champs (nombre de colonnes). | ||
- | <code bash> | + | <code user> |
- | awk '{ print NR, NF, $0 }' file.txt | + | awk '{ print NR, NF, $0 }' file.txt</code> |
+ | <code> | ||
1 3 Nom Genre Age | 1 3 Nom Genre Age | ||
2 1 --------------------------------------- | 2 1 --------------------------------------- | ||
Ligne 108: | Ligne 115: | ||
* FS : Séparateur de champ (par défaut : espace/tabulation). | * FS : Séparateur de champ (par défaut : espace/tabulation). | ||
* OFS : Séparateur de champ en sortie (par défaut : espace). | * OFS : Séparateur de champ en sortie (par défaut : espace). | ||
- | <code bash> | + | <code user> |
- | awk '/CAMILLE/ { OFS="," ; print $2,$1 }' file.txt | + | awk '/CAMILLE/ { OFS="," ; print $2,$1 }' file.txt</code> |
+ | <code> | ||
M,CAMILLE</code> | M,CAMILLE</code> | ||
Ligne 116: | Ligne 124: | ||
==== Scripts awk ==== | ==== Scripts awk ==== | ||
- | awk a été utilisé précédemment en mode lignes de commande. Lorsque le programme awk devient complexe, ce dernier peut être stocké dans un fichier : | + | <note warning>**ATTENTION** ! Vérifiez toujours l'écriture de chaque script donné ici avant de l'appliquer ! \\ |
- | prog.awk | + | Voir : **[[doc:programmation:shell:regexp#les_caracteres_echappes | Les Regexp.]]** //Et c'est pas la peine de faire Ouch..! Tuto inévitable à ce niveau.// :-P</note> |
- | <code bash> | + | |
- | cat > prog.awk | + | awk a été utilisé précédemment en mode lignes de commande. Lorsque le programme awk devient complexe, ce dernier peut être stocké dans un fichier ''prog.awk'' comme ici : |
+ | <code awk prog.awk> | ||
/^CL/,/^E/ { | /^CL/,/^E/ { | ||
- | print NR, $0 | + | print NR, \$0 |
- | }</code> | + | } |
+ | </code> | ||
Puis interprété grâce à l'option -f : | Puis interprété grâce à l'option -f : | ||
- | <code bash> | + | <code user> |
- | awk -f prog.awk file.txt | + | awk -f prog.awk file.txt</code> |
+ | <code> | ||
5 CLARA F 11 | 5 CLARA F 11 | ||
6 CLEMENT M 7 | 6 CLEMENT M 7 | ||
7 EMMA F 6</code> | 7 EMMA F 6</code> | ||
- | ==== Titre ==== | + | ==== Pré et Post opérations ==== |
+ | |||
+ | <note warning>**ATTENTION** ! Vérifiez toujours l'écriture de chaque script donné ici avant de l'appliquer !</note> | ||
+ | |||
+ | awk offre des sections pré-traitement (BEGIN) et post-traitement (END) lors de l'analyse d'un fichier. La structure du script awk est : | ||
+ | <code awk prog.awk> | ||
+ | /^CL/,/^E/ | ||
+ | BEGIN { | ||
+ | action | ||
+ | } | ||
+ | |||
+ | /filter/,/filter/ { action } | ||
+ | |||
+ | { action} | ||
+ | |||
+ | END { | ||
+ | action | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Donne : | ||
+ | <code user> | ||
+ | awk -f prog.awk file.txt</code> | ||
+ | <code> | ||
+ | CLARA F 11 | ||
+ | CLEMENT M 7 | ||
+ | EMMA F 6</code> | ||
+ | |||
+ | Les blocs BEGIN et END ne sont pas obligatoires. Il peut y avoir un bloc BEGIN sans bloc END, un bloc END sans bloc BEGIN, ou aucun de ces 2 blocs. | ||
+ | |||
+ | Des scripts bien plus complexes peuvent alors être écrits. Par exemple, extraire 2 colonnes en remplaçant les tabulations par des ";" et afficher le nombre de lignes à la fin : | ||
+ | <code awk prog.awk> | ||
+ | BEGIN { | ||
+ | FS=" " | ||
+ | OFS=";" | ||
+ | } | ||
+ | { | ||
+ | print $1, $3 | ||
+ | } | ||
+ | END { | ||
+ | printf "\nThe file has %d lines\n", NR | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | <code user> | ||
+ | awk -f prog.awk file.txt</code> | ||
+ | <code> | ||
+ | Nom;Age | ||
+ | ---------------------------------------; | ||
+ | CAMILLE;7 | ||
+ | CHLOE;12 | ||
+ | CLARA;11 | ||
+ | CLEMENT;7 | ||
+ | EMMA;6 | ||
+ | THEO;8 | ||
+ | |||
+ | The file has 8 lines </code> | ||
+ | |||
+ | <note warning>**ATTENTION** ! Vérifiez toujours l'écriture de chaque script donné ici avant de l'appliquer !</note> | ||
+ | |||
+ | |||
+ | ===== Fonctions ===== | ||
+ | |||
+ | Le parseur awk offre beaucoup de fonctions internes très utiles pour traiter les données. \\ | ||
+ | Consulter les manuels de l'utilitaire awk pour la liste complète des fonctions internes, en voici une liste partielle : | ||
+ | |||
+ | ==== toupper tolower ==== | ||
+ | |||
+ | Convertir du texte en majuscules ou en minuscules avec les fonctions toupper et tolower | ||
+ | <code user> | ||
+ | awk '/THEO/ { print $1, tolower($1) }' file.txt</code> | ||
+ | <code> | ||
+ | THEO theo</code> | ||
+ | |||
+ | ==== int ==== | ||
+ | |||
+ | Convertir une valeur en entier avec la fonction **int** : | ||
+ | <code user> | ||
+ | awk '/CHLOE/ { print $3, int($3/5)}' file.txt</code> | ||
+ | <code> | ||
+ | 12 2</code> | ||
+ | |||
+ | ==== printf ==== | ||
+ | |||
+ | La fonction printf avec awk fonctionne comme la fonction printf en C afin de formater la sortie : | ||
+ | <code user> | ||
+ | awk 'NR > 2 { printf "%10s %02d %-10s\n", $1,$3, $1}' file.txt | ||
+ | |||
+ | CAMILLE 07 CAMILLE | ||
+ | CHLOE 12 CHLOE | ||
+ | CLARA 11 CLARA | ||
+ | CLEMENT 07 CLEMENT | ||
+ | EMMA 06 EMMA | ||
+ | THEO 08 THEO </code> | ||
+ | |||
+ | ==== length ==== | ||
+ | |||
+ | Afficher la taille d'une chaîne de caractères avec la fonction length : | ||
+ | <code user> | ||
+ | awk '/CLEM/ { print $1, length($1) }' file.txt</code> | ||
+ | <code> | ||
+ | CLEMENT 7</code> | ||
+ | |||
+ | ==== match ==== | ||
+ | |||
+ | Retourne la position d'une chaîne de caractères remplissant les critères d'une expression régulière avec la fonction match : | ||
+ | <code user> | ||
+ | awk 'NR >2 { print $1, match($1,"A")}' file.txt</code> | ||
+ | <code> | ||
+ | CAMILLE 2 | ||
+ | CHLOE 0 | ||
+ | CLARA 3 | ||
+ | CLEMENT 0 | ||
+ | EMMA 4 | ||
+ | THEO 0</code> | ||
+ | |||
+ | ==== gsub ==== | ||
+ | |||
+ | Remplacer des chaînes de caractères avec la fonction gsub : | ||
+ | <code user> | ||
+ | awk 'NR >2 { gsub("A","_",$1) ; print $1 }' file.txt</code> | ||
+ | <code> | ||
+ | C_MILLE | ||
+ | CHLOE | ||
+ | CL_R_ | ||
+ | CLEMENT | ||
+ | EMM_ | ||
+ | THEO</code> | ||
+ | |||
+ | ==== substr ==== | ||
+ | |||
+ | Extraire une portion de texte avec la fonction substr : | ||
+ | <code user> | ||
+ | awk '{ print $1, substr($1,2,3) }' file.txt</code> | ||
+ | <code> | ||
+ | Nom om | ||
+ | --------------------------------------- --- | ||
+ | CAMILLE AMI | ||
+ | CHLOE HLO | ||
+ | CLARA LAR | ||
+ | CLEMENT LEM | ||
+ | EMMA MMA | ||
+ | THEO HEO</code> | ||
+ | |||
+ | ==== Fonctions utilisateur ==== | ||
+ | |||
+ | La possibilité de créer des fonctions utilisateur est une des fonctionnalités les plus importantes de l'utilitaire awk. Les fonctions sont définies avec le mot clé **function**. | ||
+ | <code awk prog.awk> | ||
+ | function gentag(nom,age) { | ||
+ | tmp=tolower(substr(nom,1,3)) | ||
+ | return tmp "_" age | ||
+ | } | ||
+ | |||
+ | BEGIN { | ||
+ | FS=" " | ||
+ | OFS=";" | ||
+ | } | ||
+ | |||
+ | { | ||
+ | print $1, $3, gentag($1,$3) | ||
+ | } | ||
+ | |||
+ | END { | ||
+ | print NR , "lines" | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code user> | ||
+ | awk -f prog.awk file.txt</code> | ||
+ | <code> | ||
+ | Nom;Age;nom_Age | ||
+ | ---------------------------------------;;---_ | ||
+ | CAMILLE;7;cam_7 | ||
+ | CHLOE;12;chl_12 | ||
+ | CLARA;11;cla_11 | ||
+ | CLEMENT;7;cle_7 | ||
+ | EMMA;6;emm_6 | ||
+ | THEO;8;the_8 | ||
+ | 8;lines</code> | ||
+ | |||
+ | ===== Programmation ===== | ||
+ | |||
+ | Le parseur awk offre toutes les structures de programmation : conditions, boucles, itérations. | ||
+ | |||
+ | ==== Condition ==== | ||
+ | |||
+ | Les enfants sont ils en primaire ou au collège avec if() {} else {} ? | ||
+ | <code awk prog.awk> | ||
+ | BEGIN { | ||
+ | OFS="," | ||
+ | } | ||
+ | NR <=2 { next } | ||
+ | { | ||
+ | if ( $3 < 11 ) { | ||
+ | ecole="primaire" | ||
+ | } else { | ||
+ | ecole="college" | ||
+ | } | ||
+ | |||
+ | print $1, ecole | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code user> | ||
+ | awk -f prog.awk file.txt</code> | ||
+ | <code> | ||
+ | CAMILLE,primaire | ||
+ | CHLOE,college | ||
+ | CLARA,college | ||
+ | CLEMENT,primaire | ||
+ | EMMA,primaire | ||
+ | THEO,primaire</code> | ||
+ | |||
+ | <note tip>Remarquer la façon dont l'entête est écartée : NR <=2 { next }</note> | ||
+ | |||
+ | ==== Boucles ==== | ||
+ | |||
+ | Remplacer l'âge de l'enfant par un nombre de points avec while() {}. | ||
+ | <code awk prog.awk> | ||
+ | NR <=2 { next } | ||
+ | { | ||
+ | min=1 | ||
+ | printf "%-10s", $1 | ||
+ | while ( min <= $3 ) { | ||
+ | printf "." | ||
+ | min++ | ||
+ | } | ||
+ | printf "\n" | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code user> | ||
+ | awk -f prog.awk file.txt</code> | ||
+ | <code> | ||
+ | CAMILLE ....... | ||
+ | CHLOE ............ | ||
+ | CLARA ........... | ||
+ | CLEMENT ....... | ||
+ | EMMA ...... | ||
+ | THEO ........</code> | ||
+ | |||
+ | ==== Itérations ==== | ||
+ | |||
+ | Remplacer l'âge de l'enfant par un nombre de points avec for (i= ; i< ; i++ ) { }. | ||
+ | <code awk prog.awk> | ||
+ | NR <=2 { next } | ||
+ | { | ||
+ | printf "%-10s", $1 | ||
+ | for ( min=1 ; min <= $3; min++ ) { | ||
+ | printf "." | ||
+ | } | ||
+ | printf "\n" | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code user> | ||
+ | awk -f prog.awk file.txt</code> | ||
+ | <code> | ||
+ | CAMILLE ....... | ||
+ | CHLOE ............ | ||
+ | CLARA ........... | ||
+ | CLEMENT ....... | ||
+ | EMMA ...... | ||
+ | THEO ........</code> | ||
+ | |||
+ | ==== Tableaux (Arrays) ==== | ||
+ | |||
+ | Pour terminer cette brève présentation : les tableaux avec awk, particulièrement pratiques pour calculer des agrégats. \\ | ||
+ | La structure d'un tableau avec awk est très simple : | ||
+ | |||
+ | tab[indice] = value | ||
+ | |||
+ | Calculer la moyenne d'âge des enfants par sexe : | ||
+ | <code awk prog.awk> | ||
+ | { | ||
+ | if ( NR <= 2 ) { next } # skip first 2 lines | ||
+ | tab_age[$2]+=$3 | ||
+ | tab_cpt[$2]++ | ||
+ | } | ||
+ | END { | ||
+ | for ( genre in tab_age ) { | ||
+ | print genre, " : ", "Moy :", int(tab_age[genre]/tab_cpt[genre]), "ans", "nb :", tab_cpt[genre] | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code user> | ||
+ | awk -f prog.awk file.txt</code> | ||
+ | <code> | ||
+ | F : Moy : 9 ans nb : 3 | ||
+ | M : Moy : 7 ans nb : 3</code> | ||
+ | |||
+ | <note tip>Remarquer comment les 2 tableaux sont remplis et traités à la fin.</note> | ||
+ | |||
+ | |||
+ | ===== Lien ===== | ||
+ | |||
+ | Un lieu formidable là : | ||
+ | * [[http://www.sqlpac.com/articles/unix-linux/outils | Outil Linux - **SQLPAC** SQL Pour Administrateurs & Concepteurs]] | ||
- | //À suivre...// **Jojo** ;-) |