Le Langage De Programmation Awk
Maybe your like
- Principe
- Opérateurs
- La fonction printf
- Redirections
- Lecture de la ligne suivante : next
- Structures de controle
- Terminer un script
- Tableaux
- Les arguments de la ligne de commande
- Fonctions intégrées
- Fonctions utilisateur
- Exemples de scripts
Liens transversaux de livre pour Trucs & Astuces
- Script sed
- Haut
- Principe
Extrait de Wikipédia :
Awk est le plus souvent utilisé pour la production de fichiers plats aux spécifications particulières (échanges entre différents systèmes d'informations hétérogènes). Il est aussi utilisé comme "parser" de fichiers XML ou de fichiers textes pour générer des commandes SQL à partir des données extraites. Il peut être utilisé aussi pour des opérations de calculs complexes et mise en forme de données brutes pour faire des tableaux statistiques.
On distingue awk, la commande originale, du new awk (nawk), arrivée un peu plus tard sur le marché. Les implémentations GNU de awk, sont en fait des new awk. On trouve en général la commande awk dans /usr/bin sous Unix. Certains systèmes GNU/Linux le mettent dans /bin. En général, elle est dans la variable d'environnement PATH. Cependant, on peut faire des scripts en awk et le shebang (#!/usr/bin/awk -f) devient faux. Le script est donc inutilisable si le binaire n’est pas là où on l’attend.
Il agit comme un filtre programmable prenant une série de lignes en entrée (sous forme de fichiers ou directement via l'entrée standard) et écrivant sur la sortie standard, qui peut être redirigée vers un autre fichier ou programme. Un programme Awk est composé de trois blocs distincts utilisables ou non pour le traitement d'un fichier (prétraitement, traitement, posttraitement). Awk lit sur l'entrée ligne par ligne, puis sélectionne (ou non) les lignes à traiter par des expressions rationnelles (et éventuellement des numéros de lignes). Une fois la ligne sélectionnée, elle est découpée en champs selon un séparateur d'entrée indiqué dans le programme awk par le symbole FS (qui par défaut correspond au caractère espace ou tabulation). Puis les différents champs sont disponibles dans des variables : $1 (premier champ), $2 (deuxième champ), $3 (troisième champ), ..., $NF (dernier champ).
« awk » est aussi l'extension de nom de fichier utilisée pour les scripts écrits dans ce langage.
Etiquettes awk- Syntaxe
- Variables spéciales
- Critères de sélection
- Structure d'un script awk
Liens transversaux de livre pour Trucs & Astuces
- Le langage de programmation awk
- Haut
- Syntaxe
awk [-F] '{action-awk}' [ fichier1 fichier2 ..... fichiern ]
awk [-F] -f script-awk [ fichier1 fichier2 ..... fichiern ]
La commande awk prend en argument la liste des fichiers à traiter. En l'absence de noms de fichiers sur la ligne de commande, awk travaille sur les données arrivant sur son entrée standard. Cette commande peut donc être placée derrière un tube de communication.
L'option "-F" permet d'initialiser, si besoin, la variable "FS" (Field Separator) correspondant au caractère séparateur de champ.
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Principe
- Haut
- Variables spéciales
Variables prédéfinies au lancement de awk
Le tableau suivant présente les principales variables internes du langage awk présentes en mémoire dès le lancement de la commande. La valeur de ces variables peut éventuellement être modifiée en fonction de la structure des données à traiter.
| Nom de la variable | Valeur par défaut | Rôle de la variable |
|---|---|---|
| RS | Newline (\n) | Record Separator : Caractère séparateur d'enregistrement (lignes). |
| FS | Suite d'espaces et/ou de tabulations | Field Separator : Caractères séparateurs de champs. |
| OFS | Espace | Output Field Separator : Séparateur de champ utilisé pour l'affichage. |
| ORS | Newline (\n) | Output Record Separator : Caractère séparateur d'enregistrement en sortie. |
| ARGV | - | Tableau initialisé avec les arguments de la ligne de commande (options et nom du script awk exclus). |
| ARGC | - | Nombre d'éléments contenus dans le tableau ARGV. |
| ENVIRON | Variables d'environnement exportées par le shell. | Tableau contenant les variables d'environnement exportées par le shell. |
| CONVFMT | %.6g | Format de conversion des nombres en String. |
| OFMT | %.6g | Format de sortie des nombres. |
| SUBSEP | \034 | Caractère de séparation pour les routines internes des tableaux. |
Par défaut, un enregistrement correspond donc à une ligne (suite de caractères terminée par "\n").
Lorsque la variable FS est initialisée avec un minimum de 2 caractères, cette valeur est interprétée comme une expression régulière.
Variables initialisées lors du traitement d'une ligne
Les enregistrements sont traités successivement. L'enregistrement courant est automatiquement découpé en champs et un certain nombre de variables internes awk sont initialisées. Le tableau suivant donne la liste des principales variables.
| Nom de la variable | Valeur de la variable |
|---|---|
| $0 | Valeur de l'enregistrement courant |
| NF | Number of Field : Nombre de champs de l'enregistrement courant. |
| $1, $2, ... $NF | $1 contient la valeur du 1er champ, $2 la valeur du 2ème champ etc etc ... et $NF la valeur du dernier champ (NF est remplacé par sa valeur). |
| NR | Number : Indice de l'enregistrement courant (NR vaut 1 quand la 1ère ligne est en cours de traitement, puis s'incrémente dès que awk change d'enregistrement). |
| FNR | File Number : Indice de l'enregistrement courant relatif au fichier en cours de traitement. |
| FILENAME | Nom du fichier en cours de traitement. |
| RLENGTH | Longueur du string trouvé par la fonction match() |
| RSTART | Première position du string trouvé par la fonction match() |
Contrairement aux variables du shell, le symbole "$" des variables awk $1, $2 etc etc... fait partie du nom des variables.
Exemples simples
Premier exemple :
Ici, awk travaille sur le résultat de la commande ps -ef. La partie en rouge représente l'action que awk doit exécuter sur chaque ligne. Les simples quotes sont indispensables pour empêcher le shell d'interpréter les caractères destinés à la commande awk. Les instructions doivent être placées entre accolades. La fonction intégrée print va afficher à l'écran les champs 1 et 8 de chaque ligne.
$ ps -ef | awk '{print $1,$8}'UID CMDroot init...www-data /usr/sbin/apache2www-data /usr/sbin/apache2root vzctl:root -bashpostfix pickuproot psroot awkroot /usr/lib/postfix/masterpostfix qmgr$
Deuxième exemple :
La fonction print peut également recevoir des chaines de caractères en argument.
$ ps -ef | awk '{print "User : " , $1, "\tCommande : " , $8}'User : UID Commande : CMDUser : root Commande : initUser : root Commande : [kthreadd/113]User : root Commande : [khelper/113]User : root Commande : [init-logger]...User : root Commande : vzctl:User : root Commande : -bashUser : root Commande : psUser : root Commande : awkUser : root Commande : /usr/lib/postfix/master$
\t représente le caractère tabulation.
Troisième exemple :
Modification du séparateur de champ "FS" grâce à l'option "-F"
$ cat /etc/passwd | awk -F : '{print $1,$7}'root /bin/bash...nobody /bin/shlibuuid /bin/shpostfix /bin/falsesshd /usr/sbin/nologinmysql /bin/false$
Quatrième exemple :
$ cat /etc/passwd | awk -F : '{print "User : " , $1 , "\tShell : " , $7}'User : root Shell : /bin/bashUser : daemon Shell : /bin/shUser : bin Shell : /bin/shUser : sys Shell : /bin/shUser : sync Shell : /bin/syncUser : games Shell : /bin/shUser : man Shell : /bin/shUser : lp Shell : /bin/shUser : mail Shell : /bin/shUser : news Shell : /bin/shUser : uucp Shell : /bin/shUser : proxy Shell : /bin/shUser : www-data Shell : /bin/shUser : backup Shell : /bin/shUser : list Shell : /bin/shUser : irc Shell : /bin/shUser : gnats Shell : /bin/shUser : nobody Shell : /bin/shUser : libuuid Shell : /bin/shUser : postfix Shell : /bin/falseUser : sshd Shell : /usr/sbin/nologinUser : mysql Shell : /bin/false$
Si la fonction print ne reçoit pas d'argument, elle affiche $0.
$ cat /etc/passwd | awk -F : '{print}'root:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/bin/shbin:x:2:2:bin:/bin:/bin/shsys:x:3:3:sys:/dev:/bin/shsync:x:4:65534:sync:/bin:/bin/syncgames:x:5:60:games:/usr/games:/bin/shman:x:6:12:man:/var/cache/man:/bin/shlp:x:7:7:lp:/var/spool/lpd:/bin/shmail:x:8:8:mail:/var/mail:/bin/shnews:x:9:9:news:/var/spool/news:/bin/shuucp:x:10:10:uucp:/var/spool/uucp:/bin/shproxy:x:13:13:proxy:/bin:/bin/shwww-data:x:33:33:www-data:/var/www:/bin/shbackup:x:34:34:backup:/var/backups:/bin/shlist:x:38:38:Mailing List Manager:/var/list:/bin/shirc:x:39:39:ircd:/var/run/ircd:/bin/shgnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/shnobody:x:65534:65534:nobody:/nonexistent:/bin/shlibuuid:x:100:101::/var/lib/libuuid:/bin/shpostfix:x:101:104::/var/spool/postfix:/bin/falsesshd:x:102:65534::/var/run/sshd:/usr/sbin/nologinmysql:x:103:108:MySQL Server,,,:/var/lib/mysql:/bin/false$
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Syntaxe
- Haut
- Critères de sélection
Il est possible de sélectionner les enregistrements sur lesquels l'action doit être exécutée.
Syntaxe :
awk [-F] 'critère {action-awk}' [fichier1 fichier2 ... fichiern]
Le critère de sélection peut s'exprimer de différentes manières.
Expressions régulières
Les enregistrements à traiter peuvent être sélectionnés en utilisant les expressions régulières étendues (ERe).
Attention, pour utiliser les quantificateurs {x,y} d'une ERe, il faut utiliser awk avec l'option --posix
Premier exemple :
Afficher les lignes du fichier /etc/passwd contenant /bin/false
$ awk -F':' '/\/bin\/false/ {print $0}' /etc/passwdpostfix:x:101:104::/var/spool/postfix:/bin/falsemysql:x:103:108:MySQL Server,,,:/var/lib/mysql:/bin/false$
Par défaut, le critère est mis en correspondance avec $0.
Il est possible de mettre un champ particulier en correspondance avec une expression régulière. Dans ce cas, il faut utiliser l'opérateur de concordance "~" ou de non-concordance "!~".
Deuxième exemple :
Afficher les lignes du fichier /etc/passwd dont le 6ème champ commence par /usr.
$ awk -F':' '$6 ~ /^\/usr/ {print $0}' /etc/passwddaemon:x:1:1:daemon:/usr/sbin:/bin/shgames:x:5:60:games:/usr/games:/bin/sh$
Et à l'inverse
$ awk -F':' '$6 !~ /^\/usr/ {print $0}' /etc/passwdroot:x:0:0:root:/root:/bin/bashbin:x:2:2:bin:/bin:/bin/sh...postfix:x:101:104::/var/spool/postfix:/bin/falsesshd:x:102:65534::/var/run/sshd:/usr/sbin/nologinmysql:x:103:108:MySQL Server,,,:/var/lib/mysql:/bin/false$
Tests logiques
Le critère peut être une expression d'opérateurs et renvoyant la valeur de vérité vrai ou faux.
Opérateurs de tests courants
| Opérateur | Signification |
|---|---|
| < | Inférieur |
| > | Supérieur |
| <= | Inférieur ou égal |
| >= | Supérieur ou égal |
| == | Test d'égalité |
| != | Test d'inégalité |
| ~ | Correspondance avec une expression régulière |
| !~ | Non-correspondance avec une expression régulière |
| ! | Négation |
| && | Et logique |
| || | Ou logique |
| (expression) | Regroupement |
Exemple :
Afficher les champs 1 et 7 de la ligne 4 et 8 du fichier /etc/passwd
$ awk -F':' 'NR == 4 || NR == 8 {print $1,"==>",$7}' /etc/passwdsys ==> /bin/shlp ==> /bin/sh$
Le chiffre 0 et la chaîne vide sont des valeurs fausses. Toute autre valeur est vraie.
Afficher uniquement les lignes impaires du fichier /etc/passwd.
Le résultat de l'opération NR%2 représentant le reste de la division par 2 du numéro de ligne en cours de traitement, cela permet d'afficher uniquement les lignes impaires du fichier car seulement les nombres impairs renvoient un reste de division différent de 0 (donc vrai). Equivalent à NR%2!=0
$ nl /etc/passwd 1 root:x:0:0:root:/root:/bin/bash 2 daemon:x:1:1:daemon:/usr/sbin:/bin/sh 3 bin:x:2:2:bin:/bin:/bin/sh 4 sys:x:3:3:sys:/dev:/bin/sh 5 sync:x:4:65534:sync:/bin:/bin/sync 6 games:x:5:60:games:/usr/games:/bin/sh 7 man:x:6:12:man:/var/cache/man:/bin/sh 8 lp:x:7:7:lp:/var/spool/lpd:/bin/sh 9 mail:x:8:8:mail:/var/mail:/bin/sh 10 news:x:9:9:news:/var/spool/news:/bin/sh 11 uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh 12 proxy:x:13:13:proxy:/bin:/bin/sh 13 www-data:x:33:33:www-data:/var/www:/bin/sh 14 backup:x:34:34:backup:/var/backups:/bin/sh 15 list:x:38:38:Mailing List Manager:/var/list:/bin/sh 16 irc:x:39:39:ircd:/var/run/ircd:/bin/sh 17 gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh 18 nobody:x:65534:65534:nobody:/nonexistent:/bin/sh 19 libuuid:x:100:101::/var/lib/libuuid:/bin/sh 20 postfix:x:101:104::/var/spool/postfix:/bin/false 21 sshd:x:102:65534::/var/run/sshd:/usr/sbin/nologin 22 mysql:x:103:108:MySQL Server,,,:/var/lib/mysql:/bin/false$
$ awk -F':' 'NR%2 {print $0}' /etc/passwdroot:x:0:0:root:/root:/bin/bashbin:x:2:2:bin:/bin:/bin/shsync:x:4:65534:sync:/bin:/bin/syncman:x:6:12:man:/var/cache/man:/bin/shmail:x:8:8:mail:/var/mail:/bin/shuucp:x:10:10:uucp:/var/spool/uucp:/bin/shwww-data:x:33:33:www-data:/var/www:/bin/shlist:x:38:38:Mailing List Manager:/var/list:/bin/shgnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/shlibuuid:x:100:101::/var/lib/libuuid:/bin/shsshd:x:102:65534::/var/run/sshd:/usr/sbin/nologin$
A l'inverse, afficher uniquement les lignes paires.
$ awk -F':' 'NR%2==0 {print $0}' /etc/passwddaemon:x:1:1:daemon:/usr/sbin:/bin/shsys:x:3:3:sys:/dev:/bin/shgames:x:5:60:games:/usr/games:/bin/shlp:x:7:7:lp:/var/spool/lpd:/bin/shnews:x:9:9:news:/var/spool/news:/bin/shproxy:x:13:13:proxy:/bin:/bin/shbackup:x:34:34:backup:/var/backups:/bin/shirc:x:39:39:ircd:/var/run/ircd:/bin/shnobody:x:65534:65534:nobody:/nonexistent:/bin/shpostfix:x:101:104::/var/spool/postfix:/bin/falsemysql:x:103:108:MySQL Server,,,:/var/lib/mysql:/bin/false$
Afficher les champs 1 et 7 de la ligne 4 à 8 du fichier /etc/passwd
$ awk -F':' 'NR == 4 , NR == 8 {print $1,"==>",$7}' /etc/passwdsys ==> /bin/shsync ==> /bin/syncgames ==> /bin/shman ==> /bin/shlp ==> /bin/sh$
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Variables spéciales
- Haut
- Structure d'un script awk
Lorsqu'il y a un certain nombre d'actions à réaliser sur les données, il est plus confortable d'écrire un script awk. Un script awk peut contenir une section BEGIN, une section END, et 0 à x sections intermédiaires. Toute section est facultative.
BEGIN
La section BEGIN est exécutée avant le traitement du premier enregistrement des données. Elle est utilisée essentiellement pour initialiser le contexte d'exécution.
Sections intermédiaires
Il peut y avoir plusieurs sections intermédiaires qui seront exécutées sur chaque enregistrement.
END
La section END est exécutée après le traitement du dernier enregistrement des données. Elle est utilisée pour exploiter les résultats issus du traitement des données.
Commentaires
Un commentaire commence par le caractère "#" et se termine au caractère "\n" (fin de la ligne).
Variables
Des variables personnelles peuvent être créées. Une variable est définie dès qu'elle est initialisée et n'a pas besoin d'être typée. L'utilisation d'une variable qui n'a jamais été définie a pour valeur 0 dans un contexte numérique et chaine vide dans un contexte de chaine.
Exemple :
$ nl script1.awk 1 # Section BEGIN 2 BEGIN { 3 print "Section BEGIN" 4 nb_0=0 5 nb_1=0 6 nb_2=0 7 nb_3=0 8 nb_4=0 9 nb_5=0 10 nb_6=0 11 nb_7=0 12 nb_8=0 13 nb_9=0 14 } 15 # Section intermediaire 16 # Traitement des departements commancant par 0 17 $2 ~ /^0/ { 18 print "Departement commancant par 0 ==> CP : " , $3 , "DEPT : " , $5 19 nb_0+=1 20 } 21 # Section intermediaire 22 # Traitement des departements commancant par 1 23 $2 ~ /^1/ { 24 print "Departement commancant par 1 ==> CP : " , $3 , "DEPT : " , $5 25 nb_1+=1 26 } 27 # Section intermediaire 28 # Traitement des departements commancant par 2 29 $2 ~ /^2/ { 30 print "Departement commancant par 2 ==> CP : " , $3 , "DEPT : " , $5 31 nb_2+=1 32 } 33 # Section intermediaire 34 # Traitement des departements commancant par 3 35 $2 ~ /^3/ { 36 print "Departement commancant par 3 ==> CP : " , $3 , "DEPT : " , $5 37 nb_3+=1 38 } 39 # Section intermediaire 40 # Traitement des departements commancant par 4 41 $2 ~ /^4/ { 42 print "Departement commancant par 4 ==> CP : " , $3 , "DEPT : " , $5 43 nb_4+=1 44 } 45 # Section intermediaire 46 # Traitement des departements commancant par 5 47 $2 ~ /^5/ { 48 print "Departement commancant par 5 ==> CP : " , $3 , "DEPT : " , $5 49 nb_5+=1 50 } 51 # Section intermediaire 52 # Traitement des departements commancant par 6 53 $2 ~ /^6/ { 54 print "Departement commancant par 6 ==> CP : " , $3 , "DEPT : " , $5 55 nb_6+=1 56 } 57 # Section intermediaire 58 # Traitement des departements commancant par 7 59 $2 ~ /^7/ { 60 print "Departement commancant par 7 ==> CP : " , $3 , "DEPT : " , $5 61 nb_7+=1 62 } 63 # Section intermediaire 64 # Traitement des departements commancant par 8 65 $2 ~ /^8/ { 66 print "Departement commancant par 8 ==> CP : " , $3 , "DEPT : " , $5 67 nb_8+=1 68 } 69 # Section intermediaire 70 # Traitement des departements commancant par 9 71 $2 ~ /^9/ { 72 print "Departement commancant par 9 ==> CP : " , $3 , "DEPT : " , $5 73 nb_9+=1 74 } 75 # Section END 76 END { 77 print "Section END" 78 print "Nombre total de lignes : " , NR 79 print "Nombre de departements commencant par 0 : " , nb_0 80 print "Nombre de departements commencant par 1 : " , nb_1 81 print "Nombre de departements commencant par 2 : " , nb_2 82 print "Nombre de departements commencant par 3 : " , nb_3 83 print "Nombre de departements commencant par 4 : " , nb_4 84 print "Nombre de departements commencant par 5 : " , nb_5 85 print "Nombre de departements commencant par 6 : " , nb_6 86 print "Nombre de departements commencant par 7 : " , nb_7 87 print "Nombre de departements commencant par 8 : " , nb_8 88 print "Nombre de departements commencant par 9 : " , nb_9 89 } $
Section BEGIN
Initialisation des variables personnelles servant de compteur.
Sections intermédiaires
Exécution des traitements spécifiques en fonction du début du numéro des départements.
Section END
Affichage du nombre total de lignes traitées et du nombre de départements regroupés par dizaine du numéro de départements.
Exécution du script
$ awk -f script1.awk depts2012.txt Section BEGIN Departement commancant par 0 ==> CP : 01053 DEPT : AIN Departement commancant par 0 ==> CP : 02408 DEPT : AISNE Departement commancant par 0 ==> CP : 03190 DEPT : ALLIER Departement commancant par 0 ==> CP : 04070 DEPT : ALPES-DE-HAUTE-PROVENCE Departement commancant par 0 ==> CP : 05061 DEPT : HAUTES-ALPES Departement commancant par 0 ==> CP : 06088 DEPT : ALPES-MARITIMES Departement commancant par 0 ==> CP : 07186 DEPT : ARDECHE Departement commancant par 0 ==> CP : 08105 DEPT : ARDENNES Departement commancant par 0 ==> CP : 09122 DEPT : ARIEGE Departement commancant par 1 ==> CP : 10387 DEPT : AUBE Departement commancant par 1 ==> CP : 11069 DEPT : AUDE Departement commancant par 1 ==> CP : 12202 DEPT : AVEYRON Departement commancant par 1 ==> CP : 13055 DEPT : BOUCHES-DU-RHONE Departement commancant par 1 ==> CP : 14118 DEPT : CALVADOS Departement commancant par 1 ==> CP : 15014 DEPT : CANTAL Departement commancant par 1 ==> CP : 16015 DEPT : CHARENTE Departement commancant par 1 ==> CP : 17300 DEPT : CHARENTE-MARITIME Departement commancant par 1 ==> CP : 18033 DEPT : CHER Departement commancant par 1 ==> CP : 19272 DEPT : CORREZE Departement commancant par 2 ==> CP : 2A004 DEPT : CORSE-DU-SUD Departement commancant par 2 ==> CP : 2B033 DEPT : HAUTE-CORSE Departement commancant par 2 ==> CP : 21231 DEPT : COTE-D'OR Departement commancant par 2 ==> CP : 22278 DEPT : COTES-D'ARMOR Departement commancant par 2 ==> CP : 23096 DEPT : CREUSE Departement commancant par 2 ==> CP : 24322 DEPT : DORDOGNE Departement commancant par 2 ==> CP : 25056 DEPT : DOUBS Departement commancant par 2 ==> CP : 26362 DEPT : DROME Departement commancant par 2 ==> CP : 27229 DEPT : EURE Departement commancant par 2 ==> CP : 28085 DEPT : EURE-ET-LOIR Departement commancant par 2 ==> CP : 29232 DEPT : FINISTERE Departement commancant par 3 ==> CP : 30189 DEPT : GARD Departement commancant par 3 ==> CP : 31555 DEPT : HAUTE-GARONNE Departement commancant par 3 ==> CP : 32013 DEPT : GERS Departement commancant par 3 ==> CP : 33063 DEPT : GIRONDE Departement commancant par 3 ==> CP : 34172 DEPT : HERAULT Departement commancant par 3 ==> CP : 35238 DEPT : ILLE-ET-VILAINE Departement commancant par 3 ==> CP : 36044 DEPT : INDRE Departement commancant par 3 ==> CP : 37261 DEPT : INDRE-ET-LOIRE Departement commancant par 3 ==> CP : 38185 DEPT : ISERE Departement commancant par 3 ==> CP : 39300 DEPT : JURA Departement commancant par 4 ==> CP : 40192 DEPT : LANDES Departement commancant par 4 ==> CP : 41018 DEPT : LOIR-ET-CHER Departement commancant par 4 ==> CP : 42218 DEPT : LOIRE Departement commancant par 4 ==> CP : 43157 DEPT : HAUTE-LOIRE Departement commancant par 4 ==> CP : 44109 DEPT : LOIRE-ATLANTIQUE Departement commancant par 4 ==> CP : 45234 DEPT : LOIRET Departement commancant par 4 ==> CP : 46042 DEPT : LOT Departement commancant par 4 ==> CP : 47001 DEPT : LOT-ET-GARONNE Departement commancant par 4 ==> CP : 48095 DEPT : LOZERE Departement commancant par 4 ==> CP : 49007 DEPT : MAINE-ET-LOIRE Departement commancant par 5 ==> CP : 50502 DEPT : MANCHE Departement commancant par 5 ==> CP : 51108 DEPT : MARNE Departement commancant par 5 ==> CP : 52121 DEPT : HAUTE-MARNE Departement commancant par 5 ==> CP : 53130 DEPT : MAYENNE Departement commancant par 5 ==> CP : 54395 DEPT : MEURTHE-ET-MOSELLE Departement commancant par 5 ==> CP : 55029 DEPT : MEUSE Departement commancant par 5 ==> CP : 56260 DEPT : MORBIHAN Departement commancant par 5 ==> CP : 57463 DEPT : MOSELLE Departement commancant par 5 ==> CP : 58194 DEPT : NIEVRE Departement commancant par 5 ==> CP : 59350 DEPT : NORD Departement commancant par 6 ==> CP : 60057 DEPT : OISE Departement commancant par 6 ==> CP : 61001 DEPT : ORNE Departement commancant par 6 ==> CP : 62041 DEPT : PAS-DE-CALAIS Departement commancant par 6 ==> CP : 63113 DEPT : PUY-DE-DOME Departement commancant par 6 ==> CP : 64445 DEPT : PYRENEES-ATLANTIQUES Departement commancant par 6 ==> CP : 65440 DEPT : HAUTES-PYRENEES Departement commancant par 6 ==> CP : 66136 DEPT : PYRENEES-ORIENTALES Departement commancant par 6 ==> CP : 67482 DEPT : BAS-RHIN Departement commancant par 6 ==> CP : 68066 DEPT : HAUT-RHIN Departement commancant par 6 ==> CP : 69123 DEPT : RHONE Departement commancant par 7 ==> CP : 70550 DEPT : HAUTE-SAONE Departement commancant par 7 ==> CP : 71270 DEPT : SAONE-ET-LOIRE Departement commancant par 7 ==> CP : 72181 DEPT : SARTHE Departement commancant par 7 ==> CP : 73065 DEPT : SAVOIE Departement commancant par 7 ==> CP : 74010 DEPT : HAUTE-SAVOIE Departement commancant par 7 ==> CP : 75056 DEPT : PARIS Departement commancant par 7 ==> CP : 76540 DEPT : SEINE-MARITIME Departement commancant par 7 ==> CP : 77288 DEPT : SEINE-ET-MARNE Departement commancant par 7 ==> CP : 78646 DEPT : YVELINES Departement commancant par 7 ==> CP : 79191 DEPT : DEUX-SEVRES Departement commancant par 8 ==> CP : 80021 DEPT : SOMME Departement commancant par 8 ==> CP : 81004 DEPT : TARN Departement commancant par 8 ==> CP : 82121 DEPT : TARN-ET-GARONNE Departement commancant par 8 ==> CP : 83137 DEPT : VAR Departement commancant par 8 ==> CP : 84007 DEPT : VAUCLUSE Departement commancant par 8 ==> CP : 85191 DEPT : VENDEE Departement commancant par 8 ==> CP : 86194 DEPT : VIENNE Departement commancant par 8 ==> CP : 87085 DEPT : HAUTE-VIENNE Departement commancant par 8 ==> CP : 88160 DEPT : VOSGES Departement commancant par 8 ==> CP : 89024 DEPT : YONNE Departement commancant par 9 ==> CP : 90010 DEPT : TERRITOIRE Departement commancant par 9 ==> CP : 91228 DEPT : ESSONNE Departement commancant par 9 ==> CP : 92050 DEPT : HAUTS-DE-SEINE Departement commancant par 9 ==> CP : 93008 DEPT : SEINE-SAINT-DENIS Departement commancant par 9 ==> CP : 94028 DEPT : VAL-DE-MARNE Departement commancant par 9 ==> CP : 95500 DEPT : VAL-D'OISE Departement commancant par 9 ==> CP : 97105 DEPT : GUADELOUPE Departement commancant par 9 ==> CP : 97209 DEPT : MARTINIQUE Departement commancant par 9 ==> CP : 97302 DEPT : GUYANE Departement commancant par 9 ==> CP : 97411 DEPT : LA Departement commancant par 9 ==> CP : 97608 DEPT : MAYOTTE Section END Nombre total de lignes : 102 Nombre de departements commencant par 0 : 9 Nombre de departements commencant par 1 : 10 Nombre de departements commencant par 2 : 11 Nombre de departements commencant par 3 : 10 Nombre de departements commencant par 4 : 10 Nombre de departements commencant par 5 : 10 Nombre de departements commencant par 6 : 10 Nombre de departements commencant par 7 : 10 Nombre de departements commencant par 8 : 10 Nombre de departements commencant par 9 : 11 $
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Critères de sélection
- Haut
- Opérateurs
Liste des opérateurs disponible dans awk.
Opérateurs arithmétiques
| Opérateur | Arité | Signification |
|---|---|---|
| + | Binaire | Addition |
| - | Binaire | Soustraction |
| * | Binaire | Multiplication |
| / | Binaire | Division |
| % | Binaire | Modulo |
| ^ | Binaire | Exponentiation |
| ++ | Unaire | Incrémentation d'une variable d'une unité |
| -- | Unaire | Décrémentation d'une variable d'une unité |
| += | Binaire | a+=b equivalent à a=a+b |
| -= | Binaire | a-=b équivalent à a=a-b |
| *= | Binaire | a*=b équivalent à a=a*b |
| /= | Binaire | a/=b équivalent à a=a/b |
| %= | Binaire | a%=b équivalent à a=a%b |
| ^= | Binaire | a^=b équivalent à a=a^b |
Opérateurs de tests
| Opérateur | Arité | Signification |
|---|---|---|
| < | Binaire | Inférieur |
| > | Binaire | Supérieur |
| <= | Binaire | Inférieur ou égal |
| >= | Binaire | Supérieur ou égal |
| == | Binaire | Test d'égalité |
| != | Binaire | Test d'inégalité |
| ~ | Binaire | Correspondance avec une ERe |
| !~ | Binaire | Non correspondance avec une ERe |
Opérateurs logiques
| Opérateur | Arité | Signification |
|---|---|---|
| ! | Binaire | Négation |
| && | Binaire | ET logique |
| || | Binaire | OU logique |
Divers
| Opérateur | Arité | Signification |
|---|---|---|
| = | Binaire | Affectation |
| e1 ? e2 : e3 | Ternaire | Le résultat est égal à e2 si e1 est vrai, égal à e3 si e1 est faux |
| e1 e2 | Binaire | Concaténation de e1 et e2 |
Liens transversaux de livre pour Trucs & Astuces
- Structure d'un script awk
- Haut
- La fonction printf
awk propose la fonction intégrée printf similaire à celle du langage C. Elle permet de formater les affichages.
printf ("chaine",field1,field2,field3...fieldx)
chaine représente la chaine affichée à l'écran. Elle peut contenir des formats qui seront substitués par la valeur des expressions citées à la suite. Il doit y avoir autant de formats que d'expressions.
Formats souvent utilisés
| Format | Signification |
|---|---|
| %20s | Affichage d'une chaine (string) sur 20 caractères (cadrage à droite par défaut) |
| %-20s | Affichage d'une chaine (string) sur 20 caractères avec cadrage à gauche |
| %3d | Affichage d'un entier/décimal sur 3 chiffres (cadrage à droite) |
| %03d | Affichage d'un entier/décimal sur 3 chiffres (cadrage à droite) complété par des 0 à gauche |
| %-3d | Affichage d'un entier/décimal sur 3 chiffres (cadrage à gauche) |
| %+3d | Affichage d'un entier/décimal sur 3 chiffres (cadrage à droite) avec affichage systématique du signe (un nombre négatif est toujours affiché avec son signe) |
| %10.2f | Affichage d'un nombre flottant sur 10 chiffres dont 2 décimales. (cadrage à droite) |
| %+010.2f | Affichage d'un nombre flottant sur 10 chiffres dont 2 décimales, cadrage à droite, affichage systématique du signe, complétion par des 0 à gauche. |
Exemple :
$ date | awk '{printf "%10s\n%-10s\n%d\n%15d\n%015d\n%-10d\n%+10d\n%10.2f\n%+010.2f\n" , $1 , $1 , $4 , $4 , $4 , $4 , $4 , 5.2 , 5.2}' mer. # %10smer. # %-10s2012 # %d 2012 # %15d000000000002012 # %015d2012 # %-10d +2012 # %+10d 5.20 # %10.2f+000005.20 # %+010.2f$
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Opérateurs
- Haut
- Redirections
Il est possible de rediriger les sorties du script vers un fichier ou vers une commande du système.
Syntaxe
| instruction > "fichier" | Au premier appel, le fichier est ouvert en mode "écrasement", puis écriture. Les écritures suivantes se font en mode "ajout" |
| instruction >> "fichier" | Au premier appel, le fichier est ouvert en mode "ajout", puis écriture. Les écritures suivantes se font également en mode "ajout" |
| print[f] "..." | "commande" | Le résultat de la fonction print/printf est transmise sur l'entrée standard de la commande système par l'intermédiaire d'un tube (pipe) |
Exemple 1
Ouverture en mode "écrasement"
$ nl script2.awk 1 BEGIN { 2 fichier = "/root/fichier1.txt" 3 print "Ligne 1" > fichier 4 print "Ligne 2" > fichier 5 print "Ligne 3" > fichier 6 close(fichier) 7 } $ uptime > /root/fichier1.txt $ cat /root/fichier1.txt 13:47:18 up 7 days, 5:28, 0 users, load average: 0.00, 0.00, 0.00 $ awk -f script2.awk $ cat /root/fichier1.txt Ligne 1 Ligne 2 Ligne 3 $
Exemple 2
Ouverture en mode "ajout"
$ nl script3.awk 1 BEGIN { 2 fichier = "/root/fichier1.txt" 3 print "Ligne 1" >> fichier 4 print "Ligne 2" > fichier 5 print "Ligne 3" > fichier 6 close(fichier) 7 } $ uptime > /root/fichier1.txt $ cat /root/fichier1.txt 13:50:40 up 7 days, 5:31, 0 users, load average: 0.00, 0.00, 0.00 $ awk -f script3.awk $ cat /root/fichier1.txt 13:50:40 up 7 days, 5:31, 0 users, load average: 0.00, 0.00, 0.00 Ligne 1 Ligne 2 Ligne 3 $
Exemple 3
Ecriture dans un tube. Trier les lignes par users croissants. La commande sort est exécutée une seule fois puis fermée dans la section END.
$ nl /etc/passwd 1 root:x:0:0:root:/root:/bin/bash 2 daemon:x:1:1:daemon:/usr/sbin:/bin/sh 3 bin:x:2:2:bin:/bin:/bin/sh 4 sys:x:3:3:sys:/dev:/bin/sh 5 sync:x:4:65534:sync:/bin:/bin/sync 6 games:x:5:60:games:/usr/games:/bin/sh 7 man:x:6:12:man:/var/cache/man:/bin/sh 8 lp:x:7:7:lp:/var/spool/lpd:/bin/sh 9 mail:x:8:8:mail:/var/mail:/bin/sh 10 news:x:9:9:news:/var/spool/news:/bin/sh 11 uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh 12 proxy:x:13:13:proxy:/bin:/bin/sh 13 www-data:x:33:33:www-data:/var/www:/bin/sh 14 backup:x:34:34:backup:/var/backups:/bin/sh 15 list:x:38:38:Mailing List Manager:/var/list:/bin/sh 16 irc:x:39:39:ircd:/var/run/ircd:/bin/sh 17 gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh 18 nobody:x:65534:65534:nobody:/nonexistent:/bin/sh 19 libuuid:x:100:101::/var/lib/libuuid:/bin/sh 20 postfix:x:101:104::/var/spool/postfix:/bin/false 21 sshd:x:102:65534::/var/run/sshd:/usr/sbin/nologin 22 mysql:x:103:108:MySQL Server,,,:/var/lib/mysql:/bin/false $ awk -F':' '{print $0 | "sort"} END {close("sort")}' /etc/passwd backup:x:34:34:backup:/var/backups:/bin/sh bin:x:2:2:bin:/bin:/bin/sh daemon:x:1:1:daemon:/usr/sbin:/bin/sh games:x:5:60:games:/usr/games:/bin/sh gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh irc:x:39:39:ircd:/var/run/ircd:/bin/sh libuuid:x:100:101::/var/lib/libuuid:/bin/sh list:x:38:38:Mailing List Manager:/var/list:/bin/sh lp:x:7:7:lp:/var/spool/lpd:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh mysql:x:103:108:MySQL Server,,,:/var/lib/mysql:/bin/false news:x:9:9:news:/var/spool/news:/bin/sh nobody:x:65534:65534:nobody:/nonexistent:/bin/sh postfix:x:101:104::/var/spool/postfix:/bin/false proxy:x:13:13:proxy:/bin:/bin/sh root:x:0:0:root:/root:/bin/bash sshd:x:102:65534::/var/run/sshd:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync sys:x:3:3:sys:/dev:/bin/sh uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh www-data:x:33:33:www-data:/var/www:/bin/sh $
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- La fonction printf
- Haut
- Lecture de la ligne suivante : next
L'instruction next interrompt le traitement de la ligne courante et déclenche la lecture de la ligne suivante.
Exemple
Dans le script suivant, les instruction next permettent d'accélérer l'exécution en évitant le traitement de la ligne courante dans les sections suivantes celle où la ligne a été traitée.
$ nl script4.awk 1 # Section BEGIN 2 BEGIN { 3 nb_0=0 4 nb_1=0 5 nb_2=0 6 nb_3=0 7 nb_4=0 8 nb_5=0 9 nb_6=0 10 nb_7=0 11 nb_8=0 12 nb_9=0 13 } 14 # Section intermediaire 15 # Traitement des departements commancant par 0 16 $2 ~ /^0/ { 17 print "Departement commancant par 0 ==> CP : " , $3 , "DEPT : " , $5 18 nb_0+=1 19 next 20 } 21 # Section intermediaire 22 # Traitement des departements commancant par 1 23 $2 ~ /^1/ { 24 print "Departement commancant par 1 ==> CP : " , $3 , "DEPT : " , $5 25 nb_1+=1 26 next 27 } 28 # Section intermediaire 29 # Traitement des departements commancant par 2 30 $2 ~ /^2/ { 31 print "Departement commancant par 2 ==> CP : " , $3 , "DEPT : " , $5 32 nb_2+=1 33 next 34 } 35 # Section intermediaire 36 # Traitement des departements commancant par 3 37 $2 ~ /^3/ { 38 print "Departement commancant par 3 ==> CP : " , $3 , "DEPT : " , $5 39 nb_3+=1 40 next 41 } 42 # Section intermediaire 43 # Traitement des departements commancant par 4 44 $2 ~ /^4/ { 45 print "Departement commancant par 4 ==> CP : " , $3 , "DEPT : " , $5 46 nb_4+=1 47 next 48 } 49 # Section intermediaire 50 # Traitement des departements commancant par 5 51 $2 ~ /^5/ { 52 print "Departement commancant par 5 ==> CP : " , $3 , "DEPT : " , $5 53 nb_5+=1 54 next 55 } 56 # Section intermediaire 57 # Traitement des departements commancant par 6 58 $2 ~ /^6/ { 59 print "Departement commancant par 6 ==> CP : " , $3 , "DEPT : " , $5 60 nb_6+=1 61 next 62 } 63 # Section intermediaire 64 # Traitement des departements commancant par 7 65 $2 ~ /^7/ { 66 print "Departement commancant par 7 ==> CP : " , $3 , "DEPT : " , $5 67 nb_7+=1 68 next 69 } 70 # Section intermediaire 71 # Traitement des departements commancant par 8 72 $2 ~ /^8/ { 73 print "Departement commancant par 8 ==> CP : " , $3 , "DEPT : " , $5 74 nb_8+=1 75 next 76 } 77 # Section intermediaire 78 # Traitement des departements commancant par 9 79 $2 ~ /^9/ { 80 print "Departement commancant par 9 ==> CP : " , $3 , "DEPT : " , $5 81 nb_9+=1 82 next 83 } 84 # Section END 85 END { 86 print "Nombre total de lignes : " , NR 87 print "Nombre de departements commencant par 0 : " , nb_0 88 print "Nombre de departements commencant par 1 : " , nb_1 89 print "Nombre de departements commencant par 2 : " , nb_2 90 print "Nombre de departements commencant par 3 : " , nb_3 91 print "Nombre de departements commencant par 4 : " , nb_4 92 print "Nombre de departements commencant par 5 : " , nb_5 93 print "Nombre de departements commencant par 6 : " , nb_6 94 print "Nombre de departements commencant par 7 : " , nb_7 95 print "Nombre de departements commencant par 8 : " , nb_8 96 print "Nombre de departements commencant par 9 : " , nb_9 97 }$
$ awk -f script4.awk depts2012.txtDepartement commancant par 0 ==> CP : 01053 DEPT : AINDepartement commancant par 0 ==> CP : 02408 DEPT : AISNEDepartement commancant par 0 ==> CP : 03190 DEPT : ALLIERDepartement commancant par 0 ==> CP : 04070 DEPT : ALPES-DE-HAUTE-PROVENCEDepartement commancant par 0 ==> CP : 05061 DEPT : HAUTES-ALPESDepartement commancant par 0 ==> CP : 06088 DEPT : ALPES-MARITIMESDepartement commancant par 0 ==> CP : 07186 DEPT : ARDECHEDepartement commancant par 0 ==> CP : 08105 DEPT : ARDENNESDepartement commancant par 0 ==> CP : 09122 DEPT : ARIEGEDepartement commancant par 1 ==> CP : 10387 DEPT : AUBEDepartement commancant par 1 ==> CP : 11069 DEPT : AUDEDepartement commancant par 1 ==> CP : 12202 DEPT : AVEYRONDepartement commancant par 1 ==> CP : 13055 DEPT : BOUCHES-DU-RHONEDepartement commancant par 1 ==> CP : 14118 DEPT : CALVADOSDepartement commancant par 1 ==> CP : 15014 DEPT : CANTALDepartement commancant par 1 ==> CP : 16015 DEPT : CHARENTEDepartement commancant par 1 ==> CP : 17300 DEPT : CHARENTE-MARITIMEDepartement commancant par 1 ==> CP : 18033 DEPT : CHERDepartement commancant par 1 ==> CP : 19272 DEPT : CORREZEDepartement commancant par 2 ==> CP : 2A004 DEPT : CORSE-DU-SUDDepartement commancant par 2 ==> CP : 2B033 DEPT : HAUTE-CORSEDepartement commancant par 2 ==> CP : 21231 DEPT : COTE-D'ORDepartement commancant par 2 ==> CP : 22278 DEPT : COTES-D'ARMORDepartement commancant par 2 ==> CP : 23096 DEPT : CREUSEDepartement commancant par 2 ==> CP : 24322 DEPT : DORDOGNEDepartement commancant par 2 ==> CP : 25056 DEPT : DOUBSDepartement commancant par 2 ==> CP : 26362 DEPT : DROMEDepartement commancant par 2 ==> CP : 27229 DEPT : EUREDepartement commancant par 2 ==> CP : 28085 DEPT : EURE-ET-LOIRDepartement commancant par 2 ==> CP : 29232 DEPT : FINISTEREDepartement commancant par 3 ==> CP : 30189 DEPT : GARDDepartement commancant par 3 ==> CP : 31555 DEPT : HAUTE-GARONNEDepartement commancant par 3 ==> CP : 32013 DEPT : GERSDepartement commancant par 3 ==> CP : 33063 DEPT : GIRONDEDepartement commancant par 3 ==> CP : 34172 DEPT : HERAULTDepartement commancant par 3 ==> CP : 35238 DEPT : ILLE-ET-VILAINEDepartement commancant par 3 ==> CP : 36044 DEPT : INDREDepartement commancant par 3 ==> CP : 37261 DEPT : INDRE-ET-LOIREDepartement commancant par 3 ==> CP : 38185 DEPT : ISEREDepartement commancant par 3 ==> CP : 39300 DEPT : JURADepartement commancant par 4 ==> CP : 40192 DEPT : LANDESDepartement commancant par 4 ==> CP : 41018 DEPT : LOIR-ET-CHERDepartement commancant par 4 ==> CP : 42218 DEPT : LOIREDepartement commancant par 4 ==> CP : 43157 DEPT : HAUTE-LOIREDepartement commancant par 4 ==> CP : 44109 DEPT : LOIRE-ATLANTIQUEDepartement commancant par 4 ==> CP : 45234 DEPT : LOIRETDepartement commancant par 4 ==> CP : 46042 DEPT : LOTDepartement commancant par 4 ==> CP : 47001 DEPT : LOT-ET-GARONNEDepartement commancant par 4 ==> CP : 48095 DEPT : LOZEREDepartement commancant par 4 ==> CP : 49007 DEPT : MAINE-ET-LOIREDepartement commancant par 5 ==> CP : 50502 DEPT : MANCHEDepartement commancant par 5 ==> CP : 51108 DEPT : MARNEDepartement commancant par 5 ==> CP : 52121 DEPT : HAUTE-MARNEDepartement commancant par 5 ==> CP : 53130 DEPT : MAYENNEDepartement commancant par 5 ==> CP : 54395 DEPT : MEURTHE-ET-MOSELLEDepartement commancant par 5 ==> CP : 55029 DEPT : MEUSEDepartement commancant par 5 ==> CP : 56260 DEPT : MORBIHANDepartement commancant par 5 ==> CP : 57463 DEPT : MOSELLEDepartement commancant par 5 ==> CP : 58194 DEPT : NIEVREDepartement commancant par 5 ==> CP : 59350 DEPT : NORDDepartement commancant par 6 ==> CP : 60057 DEPT : OISEDepartement commancant par 6 ==> CP : 61001 DEPT : ORNEDepartement commancant par 6 ==> CP : 62041 DEPT : PAS-DE-CALAISDepartement commancant par 6 ==> CP : 63113 DEPT : PUY-DE-DOMEDepartement commancant par 6 ==> CP : 64445 DEPT : PYRENEES-ATLANTIQUESDepartement commancant par 6 ==> CP : 65440 DEPT : HAUTES-PYRENEESDepartement commancant par 6 ==> CP : 66136 DEPT : PYRENEES-ORIENTALESDepartement commancant par 6 ==> CP : 67482 DEPT : BAS-RHINDepartement commancant par 6 ==> CP : 68066 DEPT : HAUT-RHINDepartement commancant par 6 ==> CP : 69123 DEPT : RHONEDepartement commancant par 7 ==> CP : 70550 DEPT : HAUTE-SAONEDepartement commancant par 7 ==> CP : 71270 DEPT : SAONE-ET-LOIREDepartement commancant par 7 ==> CP : 72181 DEPT : SARTHEDepartement commancant par 7 ==> CP : 73065 DEPT : SAVOIEDepartement commancant par 7 ==> CP : 74010 DEPT : HAUTE-SAVOIEDepartement commancant par 7 ==> CP : 75056 DEPT : PARISDepartement commancant par 7 ==> CP : 76540 DEPT : SEINE-MARITIMEDepartement commancant par 7 ==> CP : 77288 DEPT : SEINE-ET-MARNEDepartement commancant par 7 ==> CP : 78646 DEPT : YVELINESDepartement commancant par 7 ==> CP : 79191 DEPT : DEUX-SEVRESDepartement commancant par 8 ==> CP : 80021 DEPT : SOMMEDepartement commancant par 8 ==> CP : 81004 DEPT : TARNDepartement commancant par 8 ==> CP : 82121 DEPT : TARN-ET-GARONNEDepartement commancant par 8 ==> CP : 83137 DEPT : VARDepartement commancant par 8 ==> CP : 84007 DEPT : VAUCLUSEDepartement commancant par 8 ==> CP : 85191 DEPT : VENDEEDepartement commancant par 8 ==> CP : 86194 DEPT : VIENNEDepartement commancant par 8 ==> CP : 87085 DEPT : HAUTE-VIENNEDepartement commancant par 8 ==> CP : 88160 DEPT : VOSGESDepartement commancant par 8 ==> CP : 89024 DEPT : YONNEDepartement commancant par 9 ==> CP : 90010 DEPT : TERRITOIREDepartement commancant par 9 ==> CP : 91228 DEPT : ESSONNEDepartement commancant par 9 ==> CP : 92050 DEPT : HAUTS-DE-SEINEDepartement commancant par 9 ==> CP : 93008 DEPT : SEINE-SAINT-DENISDepartement commancant par 9 ==> CP : 94028 DEPT : VAL-DE-MARNEDepartement commancant par 9 ==> CP : 95500 DEPT : VAL-D'OISEDepartement commancant par 9 ==> CP : 97105 DEPT : GUADELOUPEDepartement commancant par 9 ==> CP : 97209 DEPT : MARTINIQUEDepartement commancant par 9 ==> CP : 97302 DEPT : GUYANEDepartement commancant par 9 ==> CP : 97411 DEPT : LADepartement commancant par 9 ==> CP : 97608 DEPT : MAYOTTENombre total de lignes : 102Nombre de departements commencant par 0 : 9Nombre de departements commencant par 1 : 10Nombre de departements commencant par 2 : 11Nombre de departements commencant par 3 : 10Nombre de departements commencant par 4 : 10Nombre de departements commencant par 5 : 10Nombre de departements commencant par 6 : 10Nombre de departements commencant par 7 : 10Nombre de departements commencant par 8 : 10Nombre de departements commencant par 9 : 11$
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Redirections
- Haut
- Structures de controle
Awk propose des structures de controle que l'on retrouve dans la plupart des langages de programmation. La syntaxe est héritée du langage C.
1 - if
La partie else est facultative.
Syntaxe
if (condition) { instruction ... } else { instruction ... }
2 - for
Première syntaxe
for (initialisation ; condition ; incrementation) { instruction ... }
Deuxième syntaxe
for (cle in tableau) { print cle , tableau[cle] }
3 - while
Syntaxe
while (condition) { instruction ... }
4 - do-while
Syntaxe
do { instruction ... } while (condition)
5 - break
Le mot clé break permet d'interrompre une boucle.
Principe
while (1) { if (condition) break ; instruction ; }
6 - continue
Le mot clé continue permet de remonter immédiatement à la condition, sans exécuter la suite de la boucle.
Principe
while (1) { if (condition) continue ; instruction ; }
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Lecture de la ligne suivante : next
- Haut
- Terminer un script
L'instruction exit permet de terminer un script à tout moment en retournant un statut au système.
Exemple
{ if ( NF < 3 ) exit 1 ; print $1, $2, $3 } END { exit 0 }
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Structures de controle
- Haut
- Tableaux
Dans le langage awk, il existe 2 types de tableaux
Etiquettes awk- Tableaux indicés par un entier
- Tableaux associatifs
Liens transversaux de livre pour Trucs & Astuces
- Terminer un script
- Haut
- Tableaux indicés par un entier
L'indice de départ est au choix.
Exemple
Traitement du fichier /etc/passwd. Ligne 2, initialisation de la variable FS. Ligne 5, le contenu de la variable $1 correspondant au user est stocké dans le tableau user[] indicé à partir de 1. Ligne 8 à 10, on parcourt le tableau et on affiche le contenu en formatant l'affichage avec printf.
$ nl script5.awk 1 BEGIN { 2 FS=":" 3 } 4 { 5 user[NR]=$1 6 } 7 END { 8 for (indice = 1 ; indice <= NR ; indice++ ) { 9 printf ("User num %2d : %-20s\n" , indice , user[indice]) ; 10 } 11 }
Exécution
$ awk -f script5.awk /etc/passwd User num 1 : root User num 2 : daemon User num 3 : bin User num 4 : sys User num 5 : sync User num 6 : games User num 7 : man User num 8 : lp User num 9 : mail User num 10 : news User num 11 : uucp User num 12 : proxy User num 13 : www-data User num 14 : backup User num 15 : list User num 16 : irc User num 17 : gnats User num 18 : nobody User num 19 : libuuid User num 20 : postfix User num 21 : sshd User num 22 : mysql $
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Tableaux
- Haut
- Tableaux associatifs
Initialiser un tableau
Les tableaux associatifs ont leurs éléments indicés par une chaine de caractères. Cet indice alphanumérique est considéré comme la clé et l'élément correspondant est nommé valeur.
Exemple
Le fichier depts2012.txt liste tous les départements par numéro de région.
$ cat depts2012.txt REGION DEP CHEFLIEU TNCC NCC NCCENR 82 01 01053 5 AIN Ain 22 02 02408 5 AISNE Aisne 83 03 03190 5 ALLIER Allier 93 04 04070 4 ALPES-DE-HAUTE-PROVENCE Alpes-de-Haute-Provence 93 05 05061 4 HAUTES-ALPES Hautes-Alpes 93 06 06088 4 ALPES-MARITIMES Alpes-Maritimes 82 07 07186 5 ARDECHE Ardèche 21 08 08105 4 ARDENNES Ardennes ... 11 95 95500 2 VAL-D'OISE Val-d'Oise 01 971 97105 3 GUADELOUPE Guadeloupe 02 972 97209 3 MARTINIQUE Martinique 03 973 97302 3 GUYANE Guyane 04 974 97411 0 LA REUNION La Réunion 06 976 97608 0 MAYOTTE Mayotte $
Le script suivant doit compter le nombre de départements qu'il y a par numéro de région. La section BEGIN est vide car il n'y a pas besoin d'initialiser des variables. Ligne 3, une condition est renseignée afin de ne pas traiter la première ligne du fichier qui correspond aux en-têtes. Ligne 4, mise à jour du tableau nbdepts[] ayant comme clé la valeur du premier champ correspondant au numéro de la région et incrémenté de 1 à chaque fois que le champ 1 de la ligne traitée correspond à la clé. Ligne 7 à 9, on parcourt le tableau et on affiche les résultats.
$ nl script6.awk 1 BEGIN { 2 } 3 NR != 1{ 4 nbdepts[$1]+=1 5 } 6 END { 7 for ( region in nbdepts) { 8 printf("Region num : %02d ==> %3d departement(s)\n" , region , nbdepts[region]) 9 } 10 } $
Exécution
$ awk -f script6.awk depts2012.txt Region num : 01 ==> 1 departement(s) Region num : 02 ==> 1 departement(s) Region num : 03 ==> 1 departement(s) Region num : 04 ==> 1 departement(s) Region num : 11 ==> 8 departement(s) Region num : 06 ==> 1 departement(s) Region num : 21 ==> 4 departement(s) Region num : 22 ==> 3 departement(s) Region num : 23 ==> 2 departement(s) Region num : 31 ==> 2 departement(s) Region num : 24 ==> 6 departement(s) Region num : 25 ==> 3 departement(s) Region num : 26 ==> 4 departement(s) Region num : 41 ==> 4 departement(s) Region num : 42 ==> 2 departement(s) Region num : 43 ==> 4 departement(s) Region num : 52 ==> 5 departement(s) Region num : 53 ==> 4 departement(s) Region num : 54 ==> 4 departement(s) Region num : 72 ==> 5 departement(s) Region num : 73 ==> 8 departement(s) Region num : 74 ==> 3 departement(s) Region num : 82 ==> 8 departement(s) Region num : 83 ==> 4 departement(s) Region num : 91 ==> 5 departement(s) Region num : 93 ==> 6 departement(s) Region num : 94 ==> 2 departement(s) $
Tester l'existence d'un élément
Le mot clé in permet de tester l'existence d'une clé dans un tableau associatif. Cette expression retourne vrai si la clé est présente, faux dans le cas contraire.
cle in tableau
Cette expression peut donc être utilisée comme condition d'une structure de contrôle.
if ( cle in tableau ) { ... ... }
Supprimer un élément
Il est possible de supprimer un élément d'un tableau associatif en utilisant la syntaxe suivante.
delete tableau[cle]
La paire clé-valeur est supprimée.
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Tableaux indicés par un entier
- Haut
- Les arguments de la ligne de commande
awk fourni un mécanisme qui permet de passer des arguments à un script au moment de son appel. Les variables ARGC et ARGV sont initialisées par awk et permettent de traiter les valeurs passées sur la ligne de commandes. La syntaxe doit être obligatroirement du genre var=value et placé avant le ou les fichiers à traiter.
Exemple
Avec le fichier depts2012.txt. Ecrire un script awk permettant de rechercher dans le fichier des enregistrements bien précis en lui passant comme argument un code région (champ 1), un code département (champ 2), un code postal (champ3) ou un département (champ5).
$ cat depts2012.txt REGION DEP CHEFLIEU TNCC NCC NCCENR 82 01 01053 5 AIN Ain 22 02 02408 5 AISNE Aisne 83 03 03190 5 ALLIER Allier 93 04 04070 4 ALPES-DE-HAUTE-PROVENCE Alpes-de-Haute-Provence 93 05 05061 4 HAUTES-ALPES Hautes-Alpes 93 06 06088 4 ALPES-MARITIMES Alpes-Maritimes 82 07 07186 5 ARDECHE Ardèche 21 08 08105 4 ARDENNES Ardennes ... 11 92 92050 4 HAUTS-DE-SEINE Hauts-de-Seine 11 93 93008 3 SEINE-SAINT-DENIS Seine-Saint-Denis 11 94 94028 2 VAL-DE-MARNE Val-de-Marne 11 95 95500 2 VAL-D'OISE Val-d'Oise 01 971 97105 3 GUADELOUPE Guadeloupe 02 972 97209 3 MARTINIQUE Martinique 03 973 97302 3 GUYANE Guyane 04 974 97411 0 LA_REUNION La Réunion 06 976 97608 0 MAYOTTE Mayotte $
Le script suivant traitera au maximum 4 arguments. La variable $1 devra être strictement égale à la valeur de l'argument coderegion, la variable $2 devra être strictement égale à la valeur de l'argument codedept, la variable $3 devra être strictement égale à la valeur de l'argument codepostal et enfin la variable $5 devra être strictement égale à la valeur de l'argument dept. Tous ces arguments sont bien sûr facultatifs. Les instructions next permettent de ne pas afficher plusieurs fois une même ligne correspondante à plusieurs sections intermédiaires.
$ nl script9.awk 1 BEGIN { 2 print "ARGC = " , ARGC 3 for (i=0 ; i<ARGC ; i++) { 4 printf ("ARGV[%d] = %s\n", i , ARGV[i]) 5 } 6 } 7 $1 == coderegion { 8 print $0 9 next 10 } 11 $2 == codedept { 12 print $0 13 next 14 } 15 $3 == codepostal { 16 print $0 17 next 18 } 19 $5 == dept { 20 print $0 21 next 22 } $
Exécution du script ayant comme argument de recherche coderegion=93
$ awk -f script9.awk coderegion=93 depts2012.txt ARGC = 3 ARGV[0] = awk ARGV[1] = coderegion=93 ARGV[2] = depts2012.txt 93 04 04070 4 ALPES-DE-HAUTE-PROVENCE Alpes-de-Haute-Provence 93 05 05061 4 HAUTES-ALPES Hautes-Alpes 93 06 06088 4 ALPES-MARITIMES Alpes-Maritimes 93 13 13055 4 BOUCHES-DU-RHONE Bouches-du-Rhône 93 83 83137 2 VAR Var 93 84 84007 0 VAUCLUSE Vaucluse $
Exécution du script ayant comme argument de recherche codedept=44
$ awk -f script9.awk codedept=44 depts2012.txt ARGC = 3 ARGV[0] = awk ARGV[1] = codedept=44 ARGV[2] = depts2012.txt 52 44 44109 3 LOIRE-ATLANTIQUE Loire-Atlantique $
Exécution du script ayant comme argument de recherche codepostal=85191
$ awk -f script9.awk codepostal=85191 depts2012.txt ARGC = 3 ARGV[0] = awk ARGV[1] = codepostal=85191 ARGV[2] = depts2012.txt 52 85 85191 3 VENDEE Vendée $
Exécution du script ayant comme argument de recherche dept=VAR
$ awk -f script9.awk dept=VAR depts2012.txt ARGC = 3 ARGV[0] = awk ARGV[1] = dept=VAR ARGV[2] = depts2012.txt 93 83 83137 2 VAR Var $
Exécution du script avec tous les arguments renseignés
$ awk -f script9.awk coderegion=93 codedept=44 codepostal=75056 dept=HAUTE-SAVOIE depts2012.txt ARGC = 6 ARGV[0] = awk ARGV[1] = coderegion=93 ARGV[2] = codedept=44 ARGV[3] = codepostal=75056 ARGV[4] = dept=HAUTE-SAVOIE ARGV[5] = depts2012.txt 93 04 04070 4 ALPES-DE-HAUTE-PROVENCE Alpes-de-Haute-Provence 93 05 05061 4 HAUTES-ALPES Hautes-Alpes 93 06 06088 4 ALPES-MARITIMES Alpes-Maritimes 93 13 13055 4 BOUCHES-DU-RHONE Bouches-du-Rhône 52 44 44109 3 LOIRE-ATLANTIQUE Loire-Atlantique 82 74 74010 3 HAUTE-SAVOIE Haute-Savoie 11 75 75056 0 PARIS Paris 93 83 83137 2 VAR Var 93 84 84007 0 VAUCLUSE Vaucluse $
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Tableaux associatifs
- Haut
- Fonctions intégrées
- Les fonctions sur les chaines de caractères
- Les fonctions mathématiques
- Autres fonctions
Liens transversaux de livre pour Trucs & Astuces
- Les arguments de la ligne de commande
- Haut
- Les fonctions sur les chaines de caractères
Les chaines de caractères
En plus de fonctions de base, awk dispose également de fonctions dédiées aux traitements des chaines de caractères, facilitant ce genre d'opérations. La liste de ces fonctions est la suivante :
| Fonction de string | Description |
|---|---|
| gsub(exp,sub,str) | Substitue globalement par la chaine sub chaque expression régulière exp trouvée dans la chaine str et retourne le nombre de substitutions. Si str n'est pas indiquée, par défaut $0 est utilisé. |
| index(str,st) | Retourne la position du string st dans la chaine str, ou 0 si non trouvé. |
| length(str) | Retourne la longueur de la chaine str. Si str n'est pas indiquée, par défaut $0 est utilisé. |
| match(str,exp) | Retourne la position de l'expression régulière exp dans la chaine str, ou 0 si non trouvé. Affecte les valeurs aux variables RSTART et RLENGTH. |
| split(str,tab,sep) | Sépare la chaine str en éléments dans un tableau tab et en utilisant le séparateur sep. Si sep n'est pas renseigné, FS est utilisé par défaut. |
| sprintf("format",exp) | Retourne une chaine au lieu de l'affichage vers la sortie standard, contrairement à printf(). |
| sub(exp,sub,str) | Comme gsub(), mais ne substitue par sub que la première expression exp trouvée dans str. |
| substr(str,pos,long) | Retourne une partie du string str commançant à la position pos et de longueur long. Si long n'est pas indiqué, substr() utilise tout le reste de str. |
| tolower(str) | Met en minuscules toute la chaine str et retourne la nouvelle chaine. |
| toupper(str) | Met en majuscules toute la chaine str et retourne la nouvelle chaine. |
Exemple :
gsub : remplacer par un @ toutes les lettres a et A du fichier depts2012.txt
$ head depts2012.txt | awk '{gsub(/a|A/,"@") ; print}'REGION DEP CHEFLIEU TNCC NCC NCCENR82 01 01053 5 @IN @in22 02 02408 5 @ISNE @isne83 03 03190 5 @LLIER @llier93 04 04070 4 @LPES-DE-H@UTE-PROVENCE @lpes-de-H@ute-Provence93 05 05061 4 H@UTES-@LPES H@utes-@lpes93 06 06088 4 @LPES-M@RITIMES @lpes-M@ritimes82 07 07186 5 @RDECHE @rdèche21 08 08105 4 @RDENNES @rdennes73 09 09122 5 @RIEGE @riège$
index : connaitre la position d'un caractère dans une chaine
$ head depts2012.txt | awk '{pos=index($5,"-") ; print "Position du tiret : " , pos , "\tdans la chaine : " , $5}'Position du tiret : 0 dans la chaine : NCCPosition du tiret : 0 dans la chaine : AINPosition du tiret : 0 dans la chaine : AISNEPosition du tiret : 0 dans la chaine : ALLIERPosition du tiret : 6 dans la chaine : ALPES-DE-HAUTE-PROVENCEPosition du tiret : 7 dans la chaine : HAUTES-ALPESPosition du tiret : 6 dans la chaine : ALPES-MARITIMESPosition du tiret : 0 dans la chaine : ARDECHEPosition du tiret : 0 dans la chaine : ARDENNESPosition du tiret : 0 dans la chaine : ARIEGE$
length : connaitre le nombre de caractères dans une chaine
$ tail depts2012.txt | awk '{lg=length($5) ; printf ("Il y a %3d caracteres dans la chaine %30s\n" , lg , $5)}'Il y a 7 caracteres dans la chaine ESSONNEIl y a 14 caracteres dans la chaine HAUTS-DE-SEINEIl y a 17 caracteres dans la chaine SEINE-SAINT-DENISIl y a 12 caracteres dans la chaine VAL-DE-MARNEIl y a 10 caracteres dans la chaine VAL-D'OISEIl y a 10 caracteres dans la chaine GUADELOUPEIl y a 10 caracteres dans la chaine MARTINIQUEIl y a 6 caracteres dans la chaine GUYANEIl y a 10 caracteres dans la chaine LA_REUNIONIl y a 7 caracteres dans la chaine MAYOTTE$
match : connaitre la position d'une expression dans une chaine
$ tail depts2012.txt | awk '{pos=match($5,/-DE-/) ; printf("Position de l expression recherchee \"-DE-\" : %2d dans la chaine %20s\tRSTART = %2d\tRLENGTH = %2d\n" , pos , $5 , RSTART , RLENGTH)}'Position de l expression recherchee "-DE-" : 0 dans la chaine ESSONNE RSTART = 0 RLENGTH = -1Position de l expression recherchee "-DE-" : 6 dans la chaine HAUTS-DE-SEINE RSTART = 6 RLENGTH = 4Position de l expression recherchee "-DE-" : 0 dans la chaine SEINE-SAINT-DENIS RSTART = 0 RLENGTH = -1Position de l expression recherchee "-DE-" : 4 dans la chaine VAL-DE-MARNE RSTART = 4 RLENGTH = 4Position de l expression recherchee "-DE-" : 0 dans la chaine VAL-D'OISE RSTART = 0 RLENGTH = -1Position de l expression recherchee "-DE-" : 0 dans la chaine GUADELOUPE RSTART = 0 RLENGTH = -1Position de l expression recherchee "-DE-" : 0 dans la chaine MARTINIQUE RSTART = 0 RLENGTH = -1Position de l expression recherchee "-DE-" : 0 dans la chaine GUYANE RSTART = 0 RLENGTH = -1Position de l expression recherchee "-DE-" : 0 dans la chaine LA_REUNION RSTART = 0 RLENGTH = -1Position de l expression recherchee "-DE-" : 0 dans la chaine MAYOTTE RSTART = 0 RLENGTH = -1$
split : séparer une chaine en éléments dans un tableau
$ tail depts2012.txt | awk '/-/{split($5,tab,"-") ; printf("tab1 = %10s\ttab2 = %10s\ttab3 = %10s\n" , tab[1] , tab[2] , tab[3])}'tab1 = HAUTS tab2 = DE tab3 = SEINEtab1 = SEINE tab2 = SAINT tab3 = DENIStab1 = VAL tab2 = DE tab3 = MARNEtab1 = VAL tab2 = D'OISE tab3 =$
sprintf (contrairement à la commande printf, avec sprintf le retour chariot \n n'est pas obligatoire)
$ tail depts2012.txt | awk '/-/{split($5,tab,"-") ; chaine=sprintf("tab1 = %10s\ttab2 = %10s\ttab3 = %10s" , tab[1] , tab[2] , tab[3]) ; print chaine}'tab1 = HAUTS tab2 = DE tab3 = SEINEtab1 = SEINE tab2 = SAINT tab3 = DENIStab1 = VAL tab2 = DE tab3 = MARNEtab1 = VAL tab2 = D'OISE tab3 =$
sub : remplacer par un @ la première lettre a ou A de chaque ligne du fichier depts2012.txt
$ head depts2012.txt | awk '{sub(/a|A/,"@") ; print}'REGION DEP CHEFLIEU TNCC NCC NCCENR82 01 01053 5 @IN Ain22 02 02408 5 @ISNE Aisne83 03 03190 5 @LLIER Allier93 04 04070 4 @LPES-DE-HAUTE-PROVENCE Alpes-de-Haute-Provence93 05 05061 4 H@UTES-ALPES Hautes-Alpes93 06 06088 4 @LPES-MARITIMES Alpes-Maritimes82 07 07186 5 @RDECHE Ardèche21 08 08105 4 @RDENNES Ardennes73 09 09122 5 @RIEGE Ariège$
substr : extraire une partie d'une chaine
$ tail depts2012.txt | awk '{chaine=substr($5,1,3) ; printf("Les 3 premieres lettres de %20s sont : %3s\n" , $5 , chaine)}'Les 3 premieres lettres de ESSONNE sont : ESSLes 3 premieres lettres de HAUTS-DE-SEINE sont : HAULes 3 premieres lettres de SEINE-SAINT-DENIS sont : SEILes 3 premieres lettres de VAL-DE-MARNE sont : VALLes 3 premieres lettres de VAL-D'OISE sont : VALLes 3 premieres lettres de GUADELOUPE sont : GUALes 3 premieres lettres de MARTINIQUE sont : MARLes 3 premieres lettres de GUYANE sont : GUYLes 3 premieres lettres de LA_REUNION sont : LA_Les 3 premieres lettres de MAYOTTE sont : MAY$
tolower : convertir une chaine majuscule en minuscule
$ tail depts2012.txt | awk '{chaine=tolower($5) ; printf("%20s en minuscule : %20s\n" , $5 , chaine)}' ESSONNE en minuscule : essonne HAUTS-DE-SEINE en minuscule : hauts-de-seine SEINE-SAINT-DENIS en minuscule : seine-saint-denis VAL-DE-MARNE en minuscule : val-de-marne VAL-D'OISE en minuscule : val-d'oise GUADELOUPE en minuscule : guadeloupe MARTINIQUE en minuscule : martinique GUYANE en minuscule : guyane LA_REUNION en minuscule : la_reunion MAYOTTE en minuscule : mayotte$
toupper : convertir une chaine minuscule en majuscule
$ tail depts2012.txt | awk '{chaine=toupper($6) ; printf("%20s en MAJUSCULE : %20s\n" , $6 , chaine)}' Essonne en MAJUSCULE : ESSONNE Hauts-de-Seine en MAJUSCULE : HAUTS-DE-SEINE Seine-Saint-Denis en MAJUSCULE : SEINE-SAINT-DENIS Val-de-Marne en MAJUSCULE : VAL-DE-MARNE Val-d'Oise en MAJUSCULE : VAL-D'OISE Guadeloupe en MAJUSCULE : GUADELOUPE Martinique en MAJUSCULE : MARTINIQUE Guyane en MAJUSCULE : GUYANE Mayotte en MAJUSCULE : MAYOTTE$
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Fonctions intégrées
- Haut
- Les fonctions mathématiques
Comment changer le caractère seulement dans une colonne
Bonjour,
Merci pour tous ces éclaircissements. Je chercher à remplacer un caractère dans l'ensemble des champs d'une colonne. Comment peut on restreindre votre ligne de commande dans ce sens ?
Merci
- Répondre
Tout simplement......
.....de cette manière.
Dans le fichier suivant:
$ head stats01 Ain 1.502 Aisne 2.403 Allier 2.204 Alpes-de-Haute-Provence 2.105 Hautes-Alpes 1.706 Alpes-Maritimes 1.807 Ardèche 1.808 Ardennes 2.309 Ariège 210 Aube 2
Je vais remplacer toutes les lettres "A" ou "a" dans la seconde colonne, celle qui contient les noms des départements par le caractère "@".
Pour ce faire, je vais utiliser la fonction gsub de awk mais uniquement sur la seconde colonne à l'aide de la variable $2 ($0 = ligne entière, $1 = 1ère colonne, $2 = 2ème colonne etc etc) et je réaffiche le résultat à l'aide de la fonction printf.
$ head stats | awk '{gsub(/a|A/, "@", $2); printf "%s\t%s\t%s\n", $1, $2, $3}'01 @in 1.502 @isne 2.403 @llier 2.204 @lpes-de-H@ute-Provence 2.105 H@utes-@lpes 1.706 @lpes-M@ritimes 1.807 @rdèche 1.808 @rdennes 2.309 @riège 210 @ube 2
- Répondre
Les fonctions mathématiques
awk dispose également de fonctions dédiées aux traitements numériques. Celles-ci sont les suivantes :
| Fonction mathématique | Description |
|---|---|
| cos(r) | Cosinus de l'angle r (r en radians) |
| exp(x) | Exponentiel de x |
| int(x) | Valeur entière de x |
| log(x) | Logarithme de x |
| sin(r) | Sinus de l'angle r (r en radians) |
| sqrt(x) | Racine carrée de x |
| atan2(y,x) | Arc tangente de y/x |
| rand() | Nombre pseudo-aléatoire compris entre 0 et 1 |
| srand(n) | Réinitialise la fonction rand() |
Exemple :
cos
$ echo 50 | awk '{print cos($1)}'0.964966$
exp
$ echo 5 | awk '{print exp($1)}'148.413$
int
$ echo 5.4 | awk '{print $1 , " ==> " , int($1)}'5.4 ==> 5$
log
$ echo 5 | awk '{print log($1)}'1.60944$
sin
$ echo 50 | awk '{print sin($1)}'-0.262375$
sqrt
$ echo 81 | awk '{print sqrt($1)}'9$
atan2
$ echo 50 25 | awk '{print atan2($1,$2)}'1.10715$
rand
$ echo | awk '{print rand()}'0.795735$ echo | awk '{print rand()}'0.321886$ echo | awk '{print int(rand()*1000)}'792$
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Les fonctions sur les chaines de caractères
- Haut
- Autres fonctions
- La fonction getline
- La fonction close
- La fonction system
Liens transversaux de livre pour Trucs & Astuces
- Les fonctions mathématiques
- Haut
- La fonction getline
La fonction getline permet de lire la ligne suivante du flux sans remonter au début du traitement (contrairement à next) et de lire une ligne à partir d'un fichier, de l'entrée standard ou d'un tube.
Valeur de retour : - 1 en cas de succès - 0 en fin de fichier - -1 en cas d'erreur
Il ne faut pas mettre de parenthèse lors de l'appel de la fonction getline.
Syntaxe
getline [variable] Lecture de la ligne suivante du flux. getline [variable] < "fichier" Lecture d'une ligne à partir d'un fichier "commande" | getline [variable] Lecture d'une ligne provenant du résultat d'une commande du système.
La ligne lue par getline est stockée dans la variable variable ou $0 si aucun nom de variable n'est spécifié. Le nom de fichier "-" représente l'entrée standard.
Premier exemple :
Reconstituer des phrases écrites sur plusieurs lignes et délimitées par un caractère spécifique.
Le fichier suivant contient des phrases scindées en plusieurs lignes. Le scindement est caractérisé par un anti-slash en fin de ligne.
$ cat text.txt Lorem ipsum dolor sit amet, consectetuer adipiscing elit. \ Maecenas porttitor congue massa. \ Fusce posuere, magna sed pulvinar ultricies,purus lectus malesuada libero, \ sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim. \ Fusce est. \ Vivamus a tellus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. \ Proin pharetra nonummy pede. Mauris et orci. Aenean nec lorem. In porttitor. Donec laoreet nonummy augue. Suspendisse dui purus, scelerisque at, vulputate vitae, pretium mattis, nunc. \ Mauris eget neque at sem venenatis eleifend. \ Ut nonummy. $.
Le script suivant va analyser chaque ligne du fichier et reconstituer l'intégralité des phrases grâce à la fonction getline.
$ nl script10.awk 1 { 2 ligne=$0 3 # Tant que la ligne se termine par \ 4 while(ligne ~ /\\$/){ 5 # Suppression de \ 6 sub(/\\$/,"",ligne) 7 # Lecture de la ligne suivante 8 getline nextline 9 # Concatenation de ligne et nextline 10 ligne=ligne nextline 11 } 12 # Affichage de la ligne globale 13 printf("------- Contenu de la phrase %d -------\n%s\n",++num,ligne) 14 } $
Exécution du script
$ awk -f script10.awk text.txt ------- Contenu de la phrase 1 ------- Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies,purus lectus malesuada libero, sit amet commodo magna eros quis urna. ------- Contenu de la phrase 2 ------- Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus. ------- Contenu de la phrase 3 ------- Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci. ------- Contenu de la phrase 4 ------- Aenean nec lorem. In porttitor. Donec laoreet nonummy augue. ------- Contenu de la phrase 5 ------- Suspendisse dui purus, scelerisque at, vulputate vitae, pretium mattis, nunc. Mauris eget neque at sem venenatis eleifend. Ut nonummy. $
Deuxième exemple :
Lire une entrée clavier et le contenu d'un fichier extérieur au flux courant.
Rechercher le nom d'un département dans le fichier depts2012.txt en saisissant son nom au clavier.
$ cat depts2012.txt REGION DEP CHEFLIEU TNCC NCC NCCENR 82 01 01053 5 AIN Ain 22 02 02408 5 AISNE Aisne 83 03 03190 5 ALLIER Allier 93 04 04070 4 ALPES-DE-HAUTE-PROVENCE Alpes-de-Haute-Provence 93 05 05061 4 HAUTES-ALPES Hautes-Alpes ... 01 971 97105 3 GUADELOUPE Guadeloupe 02 972 97209 3 MARTINIQUE Martinique 03 973 97302 3 GUYANE Guyane 04 974 97411 0 LA_REUNION La Réunion 06 976 97608 0 MAYOTTE Mayotte $
Le script suivant demande une saisie au clavier et recherche dans le fichier précédent le nom saisi.
$ nl script11.awk 1 BEGIN{ 2 # Boucle infinie 3 while(1){ 4 printf("Rechercher le nom (ctrl+d pour quitter): ") 5 # Lecture clavier sur l'entree standard "-" 6 # Arret du programme si le code retour de getline est different de 1 7 if((getline nom < "-") != 1) break 8 # Si aucun nom saisi, on recommence 9 if(length(nom)==0) continue 10 trouve="false" 11 # Boucle de lecture du fichier depts2012.txt 12 # Tant que le code retour de getline est egal a 1 13 while((getline < "depts2012.txt")==1){ 14 # Comparaison faite sans tenir compte de la casse 15 if(tolower($5)==tolower(nom)){ 16 trouve="true" 17 # Affichage du resultat trouve 18 print $0 19 # On sort de la boucle while 20 break 21 } 22 } 23 # Fermeture du fichier 24 close("depts2012.txt") 25 # Affichage du message si le nom n'a pas ete trouve 26 if(trouve=="false") print nom , "n'est pas dans le fichier" 27 } 28 # Affichage du message avant l'arret du programme 29 print "\nA bientot" 30 } $
Exécution du script
$ awk -f script11.awk Rechercher le nom (ctrl+d pour quitter): ain 82 01 01053 5 AIN Ain Rechercher le nom (ctrl+d pour quitter): somme 22 80 80021 3 SOMME Somme Rechercher le nom (ctrl+d pour quitter): Rechercher le nom (ctrl+d pour quitter): var 93 83 83137 2 VAR Var Rechercher le nom (ctrl+d pour quitter): A bientot $
Troisième exemple :
Utiliser getline pour lire le résulat d'une commande système.
$ nl script12.awk 1 BEGIN{ 2 "date" | getline 3 print "$0 = ",$0 4 for(i=1;i<=NF;i++){ 5 printf("$%d = %s\n",i,$i) 6 } 7 } $ awk -f script12.awk $0 = Tue May 15 19:35:25 CEST 2012 $1 = Tue $2 = May $3 = 15 $4 = 19:35:25 $5 = CEST $6 = 2012 $
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- Autres fonctions
- Haut
- La fonction close
Jointure avec un getline
Bonjour
Je souhaite réaliser une jointure ou awk prendre le nom d'une ligne dans un premier fichier, le placer en champs 1 dans le fichier output, Puis il va dans un second ficher prends les noms étendus de la première ligne, et les place en champs 2.
Voici les Input fichier_1: AB-00050832 AB-00058394 AB-00050862 AB-00004123
fichier_2: AB-00050832-18....1....-8.900758 AB-00058394-10....2....-7.981418 AB-00050832-24....3....-7.634420 AB-00050862-10....4....-7.621671 AB-00004123-1.....5....-7.386272 AB-00058394-6.....6....-7.383604 AB-00050832-12...14....-7.038594 AB-00050862-6....50....-6.701126
output: AB-00050832.....AB-00050832-18....1....-8.900758 ................AB-00050832-24....3....-7.634420 ................AB-00050832-12...14....-7.038594 AB-00058394.....AB-00058394-10....2....-7.981418 ................AB-00058394-6.....6....-7.383604 AB-00050862.....AB-00050862-10....4....-7.621671 ................AB-00050862-6....50....-6.701126 AB-00004123.....AB-00004123-1.....5....-7.386272
Il est juste important de garder l'ordre dans lequel apparaît le nom dans fichier_1. J'ai essayé avec un getline mais j'ai l'impression qu'il y a quelque chose que je n'arrive pas à débloquer. (J'ai rajouté des points car les espaces n'étaient pas pris en compte)
Si vous avez une idée, merci beaucoup!
- Répondre
Jointure avec un getline
Bonjour, La commande join peut répondre à votre besoin --> à voir pourquoi le champs de la jointure est à afficher deux fois !! join - join lines of two files on a common field Sinon, avec awk, cela donne à peu près cela: awk 'BEGIN { while (getline < "fichier_2" ) { T_File[$1]=$0 } } { if (T_File[$1]) print T_File[$1] " "$0 }' fichier_1 # on affiche la ligne que si jointure possible --> présence du champs 1 dans les deux fichiers
- Répondre
Bonjour,
Voici mon idée, on lit les lignes du fichier A (fichier_1) et pour chaque valeur lue, on recherche dans le fichier B (fichier_2), à l'aide de grep, la valeur en cours de lecture du fichier A.Pour chaque ligne trouvée dans le fichier B, on affiche la valeur du fichier A suivi d'un espace et enfin la valeur du fichier B.
$ for line in $(cat A); do while read line2; do echo -n "$line "; echo "$line2"; done <<< $(grep "^$line" B); doneJe pense que ça devrait faire l'affaire
- Répondre
La fonction close permet de fermer un fichier ou un tube de communication. Si l'appel à cette fonction est omis, les ressources sont libérées à la terminaison du script.
L'ordre de fermeture est intéressant dans les cas suivants : - pouvoir se repositionner en début de fichier au sein du même processus (fermeture puis réouverture) - fermer un tube de communication pour s'en servir à nouveau - libérer les ressources au fur et à mesure des besoins (le système limite les processus, en ce qui concerne le nombre de fichiers/tubes ouverts simultanément).
Syntaxe
close("fichier") close("commande")
Il est indispensable de fermer un fichier pour pouvoir le relire à partir du début.
Exemple :
$ nl script13.awk 1 BEGIN { 2 fichier = "/root/fichier1.txt" 3 i=1 4 while(i<=10){ 5 print rand() > fichier 6 i++ 7 } 8 # Fermeture du fichier 9 close(fichier) 10 while((getline<fichier)==1){ 11 print $0 12 } 13 } $ awk -f script13.awk 0.692303 0.532958 0.423364 0.484409 0.455168 0.0133607 0.554077 0.375875 0.325945 0.164046 $
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- La fonction getline
- Haut
- La fonction system
La fonction system permet d'exécuter une commande du système.
Syntaxe
system("commande")
La fonction retourne le statut renvoyé par la commande.
Exemple :
$ awk 'BEGIN{system("uptime")}' 21:06:15 up 5 days, 2:22, 0 users, load average: 0.00, 0.00, 0.00$
Idem mais en se servant d'une variable
$ awk 'BEGIN{fic="depts2012.txt";system("ls -l " fic)}'-rw-r--r-- 1 root root 3504 May 10 14:05 depts2012.txt$
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- La fonction close
- Haut
- Fonctions utilisateur
Les fonctions personnelles peuvent être définies dans le script awk, en dehors des blocs d'instructions, ou dans un autre script qui sera également appelé par l'option -f <script>.
Une fonction se définit par le mot clé function suivi du nom de la fonction et de ses paramètres. Une fonction peut recevoir de 0 à n arguments et retourner une valeur explicite.
Syntaxe
function nom_fonction (param1, param2, ..., paramn) { instructions return valeur }
Tous les paramètres de la fonction sont des variables locales. Toute autre variable définie dans la fonction est globale.
Appel d'une fonction
valeur=nom_fonction(val1, val2, ..., valn)
Il ne doit pas y avoir d'espace entre le nom de la fonction et la parenthèse ouvrante.
Exemple
$ nl script14.awk 1 function modulo(nb){ 2 mod=nb%2 3 if(mod==0){ 4 chaine=sprintf("%d est un nombre pair" , nb) 5 } 6 else{ 7 chaine=sprintf("%d est un nombre impair" , nb) 8 } 9 return chaine 10 } 11 { 12 for(i=1;i<=NF;i++){ 13 print modulo($i) 14 } 15 } $ echo "20 21 23 56 43 2.4 rr" | awk -f script14.awk 20 est un nombre pair 21 est un nombre impair 23 est un nombre impair 56 est un nombre pair 43 est un nombre impair 2 est un nombre impair 0 est un nombre pair $
Etiquettes awkLiens transversaux de livre pour Trucs & Astuces
- La fonction system
- Haut
- Exemples de scripts
- Analyse des logs postfix
- Afficher les infos du processeur et de la mémoire dans une page web
Liens transversaux de livre pour Trucs & Astuces
- Fonctions utilisateur
- Haut
- Analyse des logs postfix
Le script suivant analyse les logs postfix et retourne le nombre de messages par code erreur SMTP. 3 niveaux de visualisation sont proposés dont le jour et le mois en cours.
Pour fonctionner, le script à besoin d'un fichier additionnel répertoriant la liste des codes erreurs et leurs descriptions.
Téléchargement des fichiers :
- codeErrorSmtp
- mail.awk
Détail du fichier codeErrorSmtp :
$ cat codeErrorSmtp X.1.0|Other address status X.1.1|Bad destination mailbox address X.1.2|Bad destination system address X.1.3|Bad destination mailbox address syntax X.1.4|Destination mailbox address ambiguous X.1.5|Destination mailbox address valid X.1.6|Mailbox has moved X.1.7|Bad sender's mailbox address syntax X.1.8|Bad sender's system address X.2.0|Other or undefined mailbox status X.2.1|Mailbox disabled, not accepting messages X.2.2|Mailbox full X.2.3|Message length exceeds administrative limit. X.2.4|Mailing list expansion problem X.3.0|Other or undefined mail system status X.3.1|Mail system full X.3.2|System not accepting network messages X.3.3|System not capable of selected features X.3.4|Message too big for system X.4.0|Other or undefined network or routing status X.4.1|No answer from host X.4.2|Bad connection X.4.3|Routing server failure X.4.4|Unable to route X.4.5|Network congestion X.4.6|Routing loop detected X.4.7|Delivery time expired X.5.0|Other or undefined protocol status X.5.1|Invalid command X.5.2|Syntax error X.5.3|Too many recipients X.5.4|Invalid command arguments X.5.5|Wrong protocol version X.6.0|Other or undefined media error X.6.1|Media not supported X.6.2|Conversion required and prohibited X.6.3|Conversion required but not supported X.6.4|Conversion with loss performed X.6.5|Conversion failed X.7.0|Other or undefined security status X.7.1|Delivery not authorized, message refused X.7.2|Mailing list expansion prohibited X.7.3|Security conversion required but not possible X.7.4|Security features not supported X.7.5|Cryptographic failure X.7.6|Cryptographic algorithm not supported X.7.7|Message integrity failure $
Détail du script commenté :
$ nl mail.awk 1 BEGIN{ 2 # Si le nombre d'arguments est egal a 1 3 # Arret du programme 4 # Il faut au moins 2 arguments (1 nom de fichier de log) 5 # Le script peut accepter plusieurs fichiers de log 6 if(ARGC==1){ 7 print "Nombre d'arguments incorrect" 8 print "Syntaxe : awk -f mail.awk fichierLogMail1 [fichierLogMailn...]" 9 exit 1 10 } 11 # Initialisation de la variable contenant le nom du fichier 12 # des codes erreurs SMTP 13 errorSmtp="codeErrorSmtp" 14 # Execution d'une commande systeme pour tester si le fichier existe 15 # Arret du programme si le fichier n'existe pas 16 if((system("test -f " errorSmtp))==1){ 17 print "Fichier codeErrorSmtp manquant" 18 exit 1 19 } 20 # Sauvegarde des donnees du fichier codeErrorSmtp 21 # dans un tableau associatif avec le code en cle 22 while((getline < errorSmtp) == 1){ 23 ligne=$0 24 split(ligne,tab,"|") 25 tabErr[tab[1]]=tab[2] 26 } 27 # Fermeture du fichier codeErrorSmtp 28 close(errorSmtp) 29 # Affichage du menu 30 while(1){ 31 # Si le choix est passe en argument 32 if(ARGV[1] ~ /^choix=/){ 33 split(ARGV[1],tab,"=") 34 choix=tab[2] 35 if(choix>=1 && choix<=3) break 36 } 37 print "Choix date" 38 print " 1 - all" 39 print " 2 - day" 40 print " 3 - month" 41 printf("Choix : ") 42 # Lecture de l'entree clavier 43 # Si erreur, on quitte la boucle while 44 if((getline choix < "-")!=1) break 45 # Si aucune saisie, reaffichage du menu 46 if(length(choix)==0) continue 47 # Si le choix est compris entre 1 et 3 on quitte la boucle while 48 if(choix>=1 && choix<=3) break 49 } 50 deb=systime() 51 # Si le choix est egal a rien on quitte le programme 52 if(choix==""){ 53 print "Bye" 54 exit 2 55 } 56 print "-------------------------------------------" 57 print "------- Analyse des fichiers de log -------" 58 print "-------------------------------------------" 59 } 60 # Lecture des fichiers de log 61 # Si la ligne courante contient l'expression recherchee 62 $0 ~ /[0-9][0-9][0-9] [0-9]\.[0-9]\.[0-9]/ && (choix==1 || (choix==2 && $1==getMonth() && $2==getDay()) || (choix==3 && $1==getMonth())) { 63 # Recherche de la position du premier caractere de l'expression xxx x.x.x 64 pos=match($0,/[0-9][0-9][0-9] [0-9]\.[0-9]\.[0-9]/) 65 # Extraction de l'expression xxx x.x.x 66 code=substr($0,pos,9) 67 # Sauvegarde de l'expression comme cle du tableau associatif 68 # et incrementation du compteur 69 codeSmtp[code]+=1 70 } 71 END{ 72 # Parcourt du tableau associatif codeSmtp 73 totalMessages=0 74 for(i in codeSmtp){ 75 # Affichage des lignes du tableau 76 # et de la description du code avec la fonction descCode 77 printf("Code %s (%-45s) ==> %5d message(s)\n",i,descCode(i),codeSmtp[i]) 78 totalMessages+=codeSmtp[i] 79 } 80 # Fin du programme 81 fin=systime() 82 duree=fin-deb 83 printf("Total : %d messages\n%d lignes traitees en %d sec\n",totalMessages,NR,duree) 84 exit 0 85 } 86 # Fonction permettant la recherche de la description du code 87 function descCode(code){ 88 # Extraction des 4 derniers caracteres du code à partir du 6eme caractere 89 codex=substr(code,6,4) 90 # Concatenation de la lettre "X" aux 4 derniers caracteres du code 91 codex="X" codex 92 # Extraction de la description en fonction du code 93 desc=tabErr[codex] 94 # Si le code erreur n'existe pas alors OK 95 desc=(desc != "" ? desc : "OK") 96 # Retour de la description au programme appelant 97 return desc 98 } 99 # Fonction permettant d'obtenir le numero du jour en cours 100 function getDay(){ 101 day=int(strftime("%d")) 102 return day 103 } 104 # Fonction permettant d'obtenir le nom du mois en cours 105 function getMonth(){ 106 month=strftime("%b") 107 return month 108 } $
Exécution du script :
$ awk -f mail.awk /var/log/mail.log Choix date 1 - all 2 - day 3 - month Choix : 3 ------------------------------------------- ------- Analyse des fichiers de log ------- ------------------------------------------- Code 554 5.7.1 (Delivery not authorized, message refused ) ==> 1992 message(s) Code 550 5.1.1 (Bad destination mailbox address ) ==> 23 message(s) Code 250 2.0.0 (OK ) ==> 1620 message(s) Total : 3635 messages 42719 lignes traitees en 0 sec $
En passant le choix de la date en argument :
$ awk -f mail.awk choix=3 /var/log/mail.log ------------------------------------------- ------- Analyse des fichiers de log ------- ------------------------------------------- Code 554 5.7.1 (Delivery not authorized, message refused ) ==> 1992 message(s) Code 550 5.1.1 (Bad destination mailbox address ) ==> 23 message(s) Code 250 2.0.0 (OK ) ==> 1620 message(s) Total : 3635 messages 42719 lignes traitees en 0 sec $
Etiquettes Postfix awkLiens transversaux de livre pour Trucs & Astuces
- Exemples de scripts
- Haut
- Afficher les infos du processeur et de la mémoire dans une page web
utilisation du script
Bonjour, sous RedHat, le nom du fichier de log se nomme maillog, mais à part ce point, le script fonctionne très bien. Merci encore. cordialement, Karl
- Répondre
Petite modification?
Bonjour,
Tout d'abord, merci pour ce script qui m'a été très utile. J'ai une petite demande de modification. Par notre serveur postfix, nous avons envoyé une campagne d'émailing et nous voudrions connaître l'état des mails envoyés (environ 13000). Je voudrai donc pouvoir entrer en paramètre du script l'adresse de l'expéditeur car sinon j'ai les infos pour toutes les adresses d'envoi. Mais je ne sais pas comment faire :/ Pensez-vous que c'est possible et si oui, comment? Merci de votre aide. Bien à vous,
- Répondre
Bonjour,
La première idée qui me vient à l'esprit est la chose suivante.
A vérifier bien sûr en faisant une comparaison manuelle
$ grep -F 'from=<[email protected]>' /var/log/mail.log | gawk -f mail.awk choix=1
Je pense que ça doit fonctionner car j'ai constaté que l'adresse mail de l'expéditeur et le code de retour sont sur la même ligne dans les fichiers de logs.
- Répondre
Pas tout à fait cela
Bonjour, Merci de ta réponse rapide. Lorsque exécute la commande ci-dessus, j'obtiens quelques lignes comme celle-ci: Feb 28 09:43:59 nom_serveur postfix/qmgr[23080]: 2D9B4221790: from=, size=5465, nrcpt=3 (queue active)
Mais pas le résultat escompté. As-tu un idée? Merci d'avance. Bien à toi.
- Répondre
C'est ce que je craignais
Utilise le lien https://www.quennec.fr/c0nt%40ct
Ce sera plus simple que via des commentaires.
J'ai une petite idée sur la question mais il faudrait faire un petit script python à la place je mense.Ce serait beaucoup plus simple.
Envoi moi un message via mon formulaire de contact de cette manière j'aurais ton adresse mail et nous pourrons communiquer plus facilement.
- Répondre
pflogsumm
Bonjour,
Via ce lien, je récupère tout ce qu'il se passe sur mon serveur postfix: https://blog.microlinux.fr/pflogsumm-centos-7/ Nickel ^^ Bonne journée.
- Répondre
pflogsumm
Bonjour Ronan,
Sur cette page, le script exécute tout ce donc j'ai besoin: https://blog.microlinux.fr/pflogsumm-centos-7/ @+
- Répondre
A chaque problème...
... sa solution
- Répondre
Exemple extrait du Linux/Magazine N° 131 d'octobre 2010 page 52.
Le script infoproc.awk utilise les fichiers virtuels /proc/cpuinfo et /proc/meminfo pour extraire les informations à afficher dans une page HTML infoproc.html. Les fichiers sont à placer en derniers paramètres et peuvent être traités différemment par les variables FILENAME et FNR. La sortie du script est redirigée vers le fichier infoproc.html.
L'en-tête et la fin de page HTML sont codés dans le bloc BEGIN et END.
Le fichier virtuel /proc/cpuinfo contient des enregistrements séparés par une ligne vide. Chaque champs des enregistrements est défini sur une ligne. Pour ce fichier, la variable de séparation d'enregistrement RS est donc égale à un saut de ligne "\n\n" et la variable de séparation des champs FS est égale à un retour-chariot "\n". Le fichier /proc/meminfo contient un seul enregistrement et les champs sont séparés par un retour-chariot, aussi les variables RS et FS n'ont pas à être modifiées entre ces fichiers.
Télécharger le script
infoproc.awk
Détail du script infoproc.awk
$ nl infoproc.awk 1 BEGIN{ 2 RS="\n\n" # Separateur d'enregistrement 3 FS="\n" # Separateur de ligne 4 # En-tete et debut de page HTML 5 print "<html>" 6 print "<head>" 7 print "<title>Informations CPU et mémoire</title>" 8 print "<style type=\"text/css\">" 9 print "table {border: solid thin; padding 10px; margin 5px}" 10 print "table.proc {color: DarkSlateBlue; border-color: DarkSlateBlue}" 11 print "table.proc caption {color: white; background: DarkSlateBlue; text-align: center}" 12 print "table.mem {color: DarkGreen; border-color: DarkGreen}" 13 print "table.mem caption {color: white; background: DarkGreen; text-align: center}" 14 print "</style>" 15 print "</head>" 16 print "<body>" 17 print "<table><tr>" 18 } 19 FILENAME ~ /cpuinfo$/ { print "<td valign=\"top\"><table class=\"proc\">"} 20 FILENAME ~ /meminfo$/ { print "<td valign=\"top\"><table class=\"mem\">"} 21 { 22 for(i=1; i<=NF; i++){ 23 split($i, cpu, ":") 24 if(i==1) print "<caption>", cpu[1], cpu[2], "</caption>" 25 else print "<tr><td>", cpu[1], "</td><td>", cpu[2], "</td></tr>" 26 } 27 print "</table></td>" 28 } 29 END{ 30 # Fin de page HTML 31 print "</tr></table>" 32 print "</body>" 33 print "</html>" 34 } $
Exécution du script
$ awk -f /root/infoproc.awk /proc/cpuinfo /proc/meminfo > /var/www/infoproc.html
Résultat obtenu
| Élément joint | Taille |
|---|---|
| infoproc.html (5.96 Ko) | 5.96 Ko |
Liens transversaux de livre pour Trucs & Astuces
- Analyse des logs postfix
- Haut
- Les commandes filtres
Tag » Apprendre Langage Awk
-
AWK : Le Langage Script De Référence Pour Le Traitement De Fichiers
-
Cours Utilisateur UNIX : La Commande Awk - FUNIX
-
[PDF] LE LANGAGE AWK
-
Tuteur Pour Le Langage AWK - Gilles HUNAULT
-
Comment Utiliser La Commande AWK Avec Des Exemples - Malekal
-
Scripts 1.1 - AWK : Manipulation De Champs | Tutos Fr - YouTube
-
Cours27 Langage De Programmation AWK - YouTube
-
Apprendre Les Commandes Linux: Awk - Linux Tips
-
UNIX Basics : La Pratique D'awk Par L'exemple: Introduction Rapide
-
Un Guide Pratique Pour Apprendre Awk - StepsBoard
-
Awk - Wikipédia
-
[PDF] Outils Pour La Manipulation Et L'Extraction De Données
-
V. Structures De Contrôles - Tutoriel Awk
-
[PDF] Chapitre 6 : AWK Et SED