Vous êtes sur la page 1sur 34

Cours SE LINUX Chapitre 2 :

Partie 1 Programmation awk

Cours inspiré du livre Linux and Unix shell programing by D. Tansley

Introduction

Si vous souhaitez formater des rapports ou extraire des morceaux de données à partir de gros fichiers texte,
awk fera le travail. Il est parfait pour la numérisation de texte et la manipulation de données.

De tous les outils de filtrage de shell, awk est le plus difficile à maîtriser dans son intégralité.

C'est peut-être lié à sa syntaxe ou à ses messages d'erreur peu significatifs. Vous apprendrez à connaître le
«syntaxe» de awk et corriger les messages d’erreur au fur et à mesure que vous progressez dans le langage
awk.

C'est vrai, le langage awk: awk est un langage de programmation à part entière.

Apprendre awk en soi peut être un defis, mais l'utilisation son utilisation en conjonction avec d'autres outils
tels que grep et sed facilite votre travail en tant que programmeur shell.

Ce cours vise à vous montrer la puissance des lignes simples awk et comment extraire des informations à
partir de fichiers texte et de chaînes. Dans ce chapitre, nous aborderons: l'extraction de champs; la
correspondance avec des expressions régulières; la comparaison de champs; la transmission de valeurs à
awk; et basique awk one-liners et scripts.

Pour obtenir les informations souhaitées, le texte doit avoir un format structuré, et j'entends par là que les
champs doivent être séparés par un délimiteur de champ. Cela peut être n'importe quoi et peut être spécifié
lorsque vous appelez awk, comme nous le verrons plus tard.

Awk est nommé d'après les personnes qui ont développé le langage, Aho, Weninberger et Kernigham. Il
existe également nawk et gawk, qui ont des fonctionnalités étendues de traitement de texte.

Dans sa fonction la plus élémentaire, la tâche d’awk consiste à analyser et à extraire des informations d’un
fichier texte ou d’une chaîne, en fonction des critères qui lui sont attribués.

Lorsque awk a obtenu ces informations, vous pouvez alors effectuer d'autres fonctions de manipulation de
texte. Les scripts awk complets sont généralement utilisés pour formater les rapports à partir de fichiers
texte.Il existe trois façons d'invoquer awk.
Vous pouvez soit spécifier awk sur la ligne de commande comme ceci:

awk [-F field-separator] 'commandes' input-file(s)

Cette méthode est celle que nous utiliserons le plus dans cette partie du cours. La deuxième méthode consiste
à insérer toutes les commandes awk dans un fichier, puis à rendre le programme awk exécutable et à avoir
l'interpréteur de commandes awk comme première ligne du script, afin qu'il puisse être appelé en tapant
simplement le nom du script. Dans les deux exemples ci-dessus d'appel à awk, veuillez noter l'utilisation de
guillemets simples qui entourent les commandes awk.

La troisième méthode consiste à insérer toutes les commandes awk dans un fichier séparé, puis à l’appeler :

awk -f awk-script-file input-files(s)

L'option -f indique que le script awk se trouve dans le fichier awk-script-file. Le ou les fichiers d'entrée sont
les fichiers que vous souhaitez analyser avec awk.

En utilisant le Tableau 5.1 comme guide, awk lit le fichier une ligne à la fois, trouve un séparateur de champ
(dans ce cas, un symbole de hachage '#') et l'affecte comme champ-n, jusqu'à ce qu'il atteigne une nouvelle
ligne (qui est le séparateur d'enregistrements par défaut). Ensuite, il classe cette ligne comme un
enregistrement. Awk recommence alors à nouveau la lecture dans la ligne suivante.

Tableau 5.1. Comment awk litles enregistrements d'un fichier

<Champ-1> <sep> <Champ-2> <sep> <Champ-3> <sep> <Champ-4 and nouvelle ligne>

P.Ahmed (Enrg. 1) # 02/99 # 48 # Green \n

J.Troll(Enrg. 2) # 07/99 # 4842 # Brown-3 \n

Modèles et actions

Toute instruction awk peut consister en un modèle ou une action, et il peut y avoir de nombreuses
instructions dans un script awk. La partie modèle décide quand une instruction d'action doit être déclenchée
ou ce qui doit la déclencher. L'action est ce que nous voulons faire avec les données. Si vous omettez la
partie du motif, l'action sera toujours exécutée.Les modèles peuvent être n'importe quelle instruction
conditionnelle, composée ou expression régulière. Le modèle contient également deux parties spéciales
appelées BEGIN et END. Vous pouvez utiliser l'instruction BEGIN pour définir les compteurs et
imprimer les en-têtes. L'instruction BEGIN est utilisée avant que toute analyse de texte ne soit réellement
effectuée sur le fichier d'entrée. L'instruction END est utilisée pour imprimer les totaux et les déclarations
de fin de rapport une fois que awk a terminé de numériser tout le texte. Si vous ne spécifiez pas de modèle,
awk correspondra ou imprimera toujours la ou les lignes.
Une action est spécifiée en plaçant les instructions entre guillemets {}. Les actions sont principalement
utilisées pour l'impression, mais pour les scripts plus longs, elles incluent généralement des instructions if et
itération (boucle) ainsi que des constructions de sortie d'itération. Si vous ne spécifiez pas l'action à
entreprendre, awk imprimera l'intégralité de l'enregistrement qu'il analyse actuellement.

Champs et enregistrements

Quand awk est exécuté, les champs qu'il analyse sont référencés par $1, $2. . . $n. Cette méthode est appelée
identité de champ. En utilisant ces identités de champ, il est facile de travailler sur chaque champ pour un
traitement ultérieur. Pour référencer uniquement les premier et troisième champs, nous utiliserions $ 1, $ 3 -
notez l'utilisation de la virgule séparant les champs. Si nous souhaitons imprimer tous les champs d'un
enregistrement contenant cinq champs, nous n'avons pas besoin de spécifier $ 1, $ 2, $ 3, $ 4, $ 5 ; à la place,
nous pouvons utiliser $0, ce qui signifie tous les champs. Lorsque awk scanne et atteint une nouvelle ligne,
il suppose qu'il a atteint la fin de l'enregistrement pour ces champs, puis continue à partir de la lecture de la
ligne suivante dans le nouvel enregistrement et attribue les champs. Pour imprimer des champs individuels
ou tous les champs, nous utilisons la commande ‘print’, qui est une action.

Extraction des champs

Voyons quelques exemples avant de poursuivre. Nous utiliserons ce fichier texte appelé grade.txt qui
contient des entrées d'une base de données locale de karaté.
$ cat grade.txt
M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansley 05/99 4712 Brown-2 12 30 28

Nous avons sept champs dans ce fichier texte, contenant


(1) le nom, (2) la date de la note, (3) le numéro de série de l'élève, (4) la ceinture décernée, (5) l'âge de
la personne, (6) les points gagnés jusqu'à présent en compétition, et (7) maximum de points disponibles
lors des compétitions.
Vue que chaque champ est séparé par des espaces, nous n'avons pas besoin d'utiliser l'option -F pour spécifier
un séparateur ou délimiteur de champ différent.
Analysons maintenant le fichier et extrayons des données.Il existe plusieurs façons d'enregistrer la sortie de
vos scripts awk à partir de l'invite du shell. Le moyen le plus simple consiste à utiliser le signe de redirection
‘> nom de fichier’. L'exemple suivant redirige toutes les sorties vers un fichier appelé wow.

$awk '{print $0}' grade.txt >wow


Si vous utilisez cette méthode, sachez qu'aucune sortie n'apparaîtra à l'écran car elle ira directement dans le
fichier. N'utilisez cette méthode que lorsque vous êtes satisfait d'obtenir les bons résultats. La deuxième
façon consiste à utiliser la commande tee, qui affichera la sortie à l'écran ainsi que l'accès à un fichier.
Par exemple, pour rediriger la sortie vers l’écran et vers un fichier appelé ‘delete_me_and_die’, j’utiliserais
cette commande, à la fin de ma commande awk ‘| tee delete_me_and_die ». Par exemple:
$ awk '{print $0}' grade.txt | tee delete_me_and_die

Utilisation d'une entrée standard


Une note rapide sur l'utilisation des entrées pour les scripts awk; en fait, cela s'applique à tout script qui prend
son entrée à partir de l'entrée standard. Pour exécuter les scripts dans ce chapitre, nous utiliserons le format
suivant : awk_script input_file.

$ belts.awk grade_student.txt

Mais nous pouvons utiliser l'un des éléments suivants à la place.En utilisant un peu de redirection :

$ belts.awk < grade2.txt

Ou à l’aide d’un pipe :

$ cat grade2.txt|belts.awk

Impression de tous les enregistrements :


awk lit dans chaque enregistrement, et comme nous n'avons pas de modèle et seulement une partie action
qui indique { print $0 } (imprimez tous les enregistrements). Comme il s'agit d'une action, nous avons joint
la déclaration entre deux accolades.

$ awk '{print $0}' grade.txt

La commande ci-dessus imprime le fichier entier.


M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansley 05/99 4712 Brown-2 12 30 28

Impression d'enregistrements individuels :


Supposons maintenant que nous voulions simplement imprimer les noms des élèves et les ceintures qui leur
ont été attribuées. En regardant les colonnes des champs, nous savons que nous avons besoin de «champ-1»
et «champ-4», donc en utilisant $ 1 et $ 4 et sans oublier de les séparer par une virgule, nous avons:
$ awk '{print $1,$4}' grade.txt
Output :
M.Tansley Green
J.Lulu green
P.Bunny Yellow
J.Troll Brown-3
L.Tansley Brown-2
Impression des en-têtes de rapport
La sortie de la dernière commande pourrait se faire avec un certain espacement entre la colonne des noms et
des ceintures pour la rendre plus présentable. Nous pouvons résoudre ce problème en plaçant des tabulations
entre la sortie des champs. Pour mettre une tabulation, nous utilisons \ t - notation abrégée pour une
tabulation. Nous pourrions également mettre un en-tête informatif pour la sortie du texte, intitulé «Nom et
ceinture» qui contiendra également un soulignement. Pour souligner le texte, nous pouvons utiliser \ n qui
force une nouvelle ligne et commence à imprimer le texte qui suit le \ n sur la ligne suivante. Nous mettons
l'en-tête du texte dans la partie du motif BEGIN. Comme nous imprimons l'en-tête, il sera classé comme une
action, nous allons donc le mettre entre guillemets. Cette rubrique sera imprimée avant que awk ne regarde
le premier enregistrement.
$ awk…………………………………………………………………………………………………………………………………………………………………………………………………………………..
Output :
Name Belt
---------------------------------------
M.Tansley Green
J.Lulu green
P.Bunny Yellow
J.Troll Brown-3
L.Tansley Brown-3

Impression de rapport :
Si nous voulons une ligne de «fin de rapport», nous pouvons utiliser l'instruction END, mais n'oubliez pas
que l’instruction END sera exécutée une fois tout le traitement de texte sur le fichier terminé. L'instruction
END tient juste après la partie action principale. Nous pouvons également coller une simple ligne d'en-tête
pour être complet:
$ awk 'BEGIN {print "Name\n-------"} {print $1} …………………………………………………………..'grade.txt
Output :
Name
-------
M.Tansley
J.Lulu
P.Bunny
J.Troll
L.Tansley
end-of-report

Expressions régulières et opérateurs dans awk


On peut spécifiez une expression régulière en la joignant à des barres obliques: ‘/ regular_expression /’. Par
exemple, si je voulais rechercher la chaîne «Green» dans notre fichier texte, nous utiliserions / Green /, qui
rechercherait toutes les occurrences du mot «Green».

Métacaractères

Voici les caractères que nous utilisons pour la correspondance des expressions régulières dans awk.

\ ^ $ . [] | () * + ?

Il y a deux caractères spéciaux qui fonctionnent en awk mais pas en grep ou sed; elles sont:

Utilisez le ‘+’ pour faire correspondre un ou plusieurs caractères.

Par exemple, pour faire correspondre une ou plusieurs des lettres t / t + / ou pour faire correspondre toute
chaîne de minuscules, utilisez / [a-z] + /

? correspondra à une occurrence du modèle. Par exemple, pour faire correspondre XYZ ou YZ, utilisez /
XY? Z /

Opérateurs condition

Le Tableau 5.2 montre les opérateurs conditionnels d’awk. Nous verrons ci-dessous quelques exemples de
ces opérateurs.

Tableau 5.2. Operateurs conditionnels de awk

Operateur Description

< Lessthan

<= Less than or equal to

== Equal to

!= Not equal to

>= Greater than or equal to

∼ Matched by regular expression

!∼ Not matched by regular expression

Matching:

Pour pouvoir faire correspondre un modèle à un numéro de champ, nous pouvons utiliser le signe tilde (∼)
qui indique à awk qu'une correspondance d'expression régulière suivra. Nous pouvons également utiliser une
clause «if». Lorsque nous utilisons le mot «if» dans awk, nous mettons la partie condition entre parenthèses
(). En regardant notre fichier grade.txt, si vous vouliez voir uniquement les ceintures brunes, et nous savons
que les grades de ceinture sont 'champ-4', nous pouvons maintenant écrire une expression qui signifie que si
'champ-4' contient 'Brown' alors imprime le. Il s'agit de l'expression '{if ($ 4 ∼ / Brown /) print}'. Si la
condition est remplie, nous voulons imprimer les enregistrements correspondants, et comme il s'agit d'une
action, nous devons mettre l'intégralité de l'instruction entre guillemets.

Chercher les ceinture uniquement brunes

$ awk '………………………………………………………………………………………' grade.txt


Output :
J.Troll 07/99 4842 Brown-31 2 26 26
L.Tansley 05/99 4712 Brown-2 12 30 28

Exact Match
Supposons que nous voulions faire une correspondance exacte sur une chaîne. Si par exemple, vous cherchiez
un numéro de série étudiant de «48». En regardant le fichier, il y a d'autres numéros de série qui contiennent
également 48. Si nous recherchions le numéro de série, 48 awk retournerait tous les autres numéros de série
qui ont 48, dans le « champ-3 » :
$ awk '{if($3∼/48/) print $0}' grade.txt
M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
Afficher seulement l’étudiant qui a le numéro exacte 48.
$ awk '…………………………………………………………………….' grade.txt
Output :
P.Bunny 02/99 48 Yellow 12 35 28

Recherche inverse
Parfois, vous voulez pouvoir analyser des informations et extraire des éléments qui ne correspondent pas.
Eh bien, l'opposé du signe de comparaison est le !~, ce qui signifie qu'il ne correspond pas.
Chercher tous les ceinture qui ne sont pas brunes.
$ awk '……………………………………….' grade.txt
Output
M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28

Si nous avions utilisé la commande awk '$ 4! = "Brown" {print $ 0}' grade.txt, cela aurait renvoyé des
résultats incorrects, car nous avons mis Brown entre guillemets, et donc il recherchera 'Brown' uniquement
et pas les catégories «Brown-2» ou «Brown-3». Bien sûr, si nous voulions rechercher des ceintures qui ne
sont pas Brown-2, nous aurions pu le faire :
$ awk '$4 != "Brown-2" {print $0}' grade.txt

Inferieur
Chercher les étudiants qui ont obtenu leurs point cible (points gagnés «champ-6» inférieurs au total possible
«champ-7», et mettre également un petit message de motivation sur le rapport.
$ awk '{……………………………………. print $0 …………………"$1 Try better at the next comp"}'
grade.txt
output:
M.Tansley Try better at the next comp
J.Lulu Try better at the next comp
Les majuscules et les minuscules
Si nous voulons pouvoir rechercher des informations, que ce soit en majuscules ou en minuscules, nous
pouvons utiliser le signe []. En utilisant une expression régulière, chercher les ceintures Green et green.
$ awk '……………………………………………………' grade.txt
Output :
M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
Tout caractère
En utilisant une expression régulière extraire tous les noms dont le quatrième caractère est un
"a" du premier champ.
$ awk '$1 ∼…………………..' grade.txt
Output :
M.Tansley 05/99 48311 Green 8 40 44
L.Tansley 05/99 4712 Brown-2 12 30 28

Matcher l'un ou l'autre


Extraire tous les ceintures jaunes (yellow) ou brunes (brown).
$ awk '……………………………………………………' grade.txt
Output
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansley 05/99 4712 Brown-2 12 30 28

Début de la ligne
Vous n'avez pas toujours à spécifier le numéro de champ que vous souhaitez. Si vous voulez trouvez tous
les codes qui ont "48" au début d’une ligne à partir d'un fichier texte, vous pouvez simplement utiliser le
signe "caret ^" comme ceci

$ awk '/^48/' input-file


Les opérateurs composés sont utilisés pour former des opérateurs logiques complexes. Tout ce que vous
avez besoin de savoir sur les composés est qu’il s’agit d’une expression qui combine d’autres modèles, et
l’expression est réalisée en utilisant les opérateurs logiques suivants :

&& AND: both sides of the statement must be true for the match

| OR: either or both sides of the statement must be true for the match

! NOT: both sides of the equation will be inverted

AND (ET)

Imprimer l’enregistrement si seulement P.Bunny est présent et il a un ceinture Jaune.

$ awk '{…………………………………………………………………………………………………………. print $0}' grade.txt


P.Bunny 02/99 48 Yellow 12 35 28

OR (OU)
Si nous voulions voir toutes les ceintures «jaunes» (Yellow) ou «brunes»(Brown), vous pouvez utiliser la
commande OU, qui indique l'une ou les deux déclarations de chaque côté du signe || peut être vrai.

$ awk '{if ($4=="Yellow" || $4∼/Brown/) print $0}' grade.txt


P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansley 05/99 4712 Brown-2 12 30 28

Variables intégrées Awk

Awk dispose d'un certain nombre de variables intégrées qui vous permettent d'obtenir plus d'informations
sur votre environnement. Vous pouvez également modifier certaines valeurs de variable. Le Tableau 5.3
montre les variables les plus utiles, et une brève explication de chaque variable suit.

Table 5.3. Variables intégrées awk

ARGC Nombre d'arguments de ligne de commande

ARGV Tableau d'arguments de ligne de commande

ENVIRON Contient les variables d'environnement système actuelles dans le tableau

FILENAME Le nom du fichier en cours d'analyse par Awk

FNR Numéro d'enregistrement dans le fichier actif

FS Définit le séparateur de champ d'entrée ; identique à l'option -


F de la ligne de commande
NF Nombre de champs dans l'enregistrement actif

NR Nombre d'enregistrements lus jusqu'à présent

OFS Séparateur de champ de sortie

ORS Séparateur d'enregistrement de sortie

RS Contrôle le séparateur d'enregistrement


L'ARGC contient le nombre d'arguments de ligne de commande qui sont passés au script awk. ARGV sont
les éléments du tableau ARGC. Ils sont accessibles en référençant ARGV [n], où n est l'argument de ligne
de commande auquel vous souhaitez accéder.

ENVIRON contient toutes les variables d'environnement définies. Pour accéder aux variables individuelles,
vous utilisez le nom réel de la variable, par exemple ENVIRON ["EDITOR"] == "vi".

FILENAME contient le fichier d'entrée actuel sur lequel le script travaille actuellement. Étant donné qu'awk
peut traiter de nombreux fichiers, cette variable, si elle est accessible, indiquera quel fichier est analysé à ce
moment-là.

FNR détient le record actuel sur lequel awk travaille ; sa valeur lors de l'accès est inférieure ou égale à NR.
Si vous accédez à de nombreux fichiers dans un script, cette variable sera réinitialisée pour chaque nouveau
fichier d'entrée.

FS est utilisé pour définir le séparateur de champ dans awk, ce qui revient à le définir avec l'option -F sur la
ligne de commande. Par défaut, c'est un espace ; si vous souhaitez accéder à des fichiers séparés par des
virgules, vous affectez la virgule comme ceci :FS = ",".

NF contient le nombre de champs pour chaque enregistrement est défini après la lecture de chaque
enregistrement.

OFS vous permet de spécifier le séparateur de champ de sortie, qui par défaut est un espace. Si vous souhaitez
le définir en tant que #, procédez comme suit: OFS = "#".

ORS est le séparateur d'enregistrement de sortie, qui par défaut est une nouvelle ligne (\ n).

RS est le séparateur d'enregistrement, qui par défaut est une nouvelle ligne (\ n).

NF, NR et FILENAME

Une façon rapide de déterminer le nombre d'enregistrements que vous avez est d’utiliser NR. Lorsque
j’exporte un fichier d’une base de données, je veux pouvoir dire rapidement combien d’enregistrements il
contient, de sorte que je peux comparer l’exporter à l'original pour des erreurs possibles durant le processus
d’exportation. Cela fait le travail, il imprime uniquement le nombre d’enregistrements dans le fichier d’entrée
«print "NR" » dans la partie de l'instruction END.
$ awk 'END {print NR}' grade.txt

Dans l'exemple suivant, tous les dossiers des étudiants sont imprimés avec les numéros d'enregistrement.
Nous pouvons utiliser la variable NF pour afficher le nombre de champs dans chaque enregistrement lu. La
partie END imprime le nom du fichier d’entrée courant.
$ awk '{print NF,NR,$0}END{print FILENAME}' grade.txt
7 1 M.Tansley 05/99 48311 Green 8 40 44
7 2 J.Lulu 06/99 48317 green 9 24 26
7 3 P.Bunny 02/99 48 Yellow 12 35 28
7 4 J.Troll 07/99 4842 Brown-3 12 26 26
7 5 L.Tansley 05/99 4712 Brown-2 12 30 28
grade.txt
Lorsque vous voulez extraire de l’information d’un fichier, il est bon de vérifier d’abord qu’il y a
effectivement des enregistrements dans le fichier. Dans l’exemple suivant, je ne veux pas chercher les
ceintures Brunes (Brown) a moins qu’il y ait au moins un enregistrement dans le fichier. Ceci est réalisé à
l’aide de l’instruction composé AND. L’exemple signifie que s’il ya plus de zéro enregistrement présent et
que la chaine "Brown" est présente imprimez-la.
$ awk '{if (NR >0 && $4∼/Brown/) print $0}' grade.txt
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansley 05/99 4712 Brown-2 12 30 28

Une bonne utilisation de NF est que vous pouvez retirer le répertoire dans lequel vous vous trouvez en
faisant un echo à la variable PWD à awk, tout en spécifiant le séparateurs de champs est "/"
$ pwd
/usr/local/etc
$ echo $PWD | awk -F/ '{print $NF}'
etc
Voici une autre utilisation, pour extraire uniquement le nom de fichier.
$ echo "/usr/local/etc/rc.sybase" | awk -F/ '{print $NF}'
rc.sybase
2.8. Les opérateurs Awk
Lors de l'utilisation des opérateurs dans awk, les expressions primaires peuvent être classée
s en tant qu’éléments numériques, chaînes, variables, champs et tableaux. Nous en
avons déjà rencontré quelques-uns, mais pour plus de détails, voici la liste des opérateurs.

= + = *= /= %= ^= Opérateurs d'affectation

? Opérateur d'expression conditionnelle

|| && ! OU, ET, NON (nous avons traité de ces questions dans la dernière section)
∼ !∼ Opérateurs de correspondance, correspondance et non-correspondance

<<= == ! =>> Opérateurs relationnels

+-* / % ^ Opérateurs arithmétiques

+ + -- Préfixe et Suffixe
Certains des exemples que nous avons mentionnés ont inclus quelques-uns des opérateurs de awk, nous
allons donc jeter un coup d’œil à ceux que nous n’avons pas encore couverts.

Affectation de champs d'entrée aux noms de variables de champ.

Lorsque vous utilisez awk, il est parfois bon d’attribuer des noms significatifs aux champs, ce qui peut
faciliter la compréhension des commandes si vous effectuez des correspondances de motifs ou d’autres
opérations relationnelles. La construction générale sur l’assignation de nom de variable ‘name=$n’, où name
est la variable que vous voulez appeler ce champ et $n est le numéro de champ réel. Si vous voulez attribuer
la variable "nom" aux noms des étudiants et "ceintures" aux notes des étudiants, cela se fera comme
suit : ‘name=$1 ; belts=$4’, notez l’utilisation du point-virgule qui sépare les commande awk.

Dans cet exemple, nous avons réaffecté le champ des noms d'étudiants au nom(name) et le champ de grade
aux ceintures a belts (ceintures). Nous testons ensuite les ceintures Jaunes (Yellow) dans le champ de
ceintures et nous imprimons finalement le nom de la ceinture.

$ awk '{name=$1;belts=$4; if(belts ∼/Yellow/)print name" is belt"belts}' grade.txt


P.Bunny is belt Yellow
Comparaison de champs avec des valeurs

Il existe deux façons de tester si un champ numérique est inférieur à un autre champ numérique.Demandez
au numéro attribué dans la partie BEGIN à un nom de variable. Utilisez le nombre réel lorsque vous
effectuez le test relationnel. Voyons tous les étudiants qui ont obtenu moins de 27 points dans leur concours.
L’utilisation de guillemets autour du nombre à tester est facultative

$ awk'{if($6 < 27)print$0}' grade.txt


J.Lulu 06/99 48317 green 9 24 26
J.Troll 07/99 4842 Brown-3 12 26 26
Pour le deuxième exemple, nous attribuons d’abord le numéro à un nom, appelons le BASELINE. Comme
nous lui donnons une valeur, nous pouvons la définir dans la partie BEGIN.

$ awk 'BEGIN {BASELINE="27 "}{if($6 < BASELINE)print$0}' grade.txt


J.Lulu 06/99 48317 green 9 24 26
J.Troll 07/99 4842 Brown-3 12 26 26

Modification des valeurs des champs numériques


Lorsque vous apportez des modifications à l'un des champs à l'aide de awk, il est important de se rappeler
que le fichier d'entrée réel N'EST PAS modifié, uniquement la copie d'awk qui est conservée dans le tampon.
Awk reconnaîtra le changement et il se reflète dans les valeurs des variables NR ou NF. Pour changer les
champs numériques, nous réaffectons simplement l’identité du champ avec une nouvelle valeur, comme
ceci: ‘$ 1 = $ 1 + 5’. Cela ajouterait «5» à la valeur du champ-1. Assurez-vous que le champ que vous ajoutez
ou soustrayez est numérique. Pour changer le champ «Points marqués jusqu'à présent» de M.Tansley de sa
valeur actuelle de «40» à «39», j'utiliserais cette affectation: «6 $ = $6 - 1 » - bien sûr, je devrais d'abord
m'assurer que avait d'abord fait correspondre le nom avec un ==, avant de procéder à cette modification.

$ awk '{if($1=="M.Tansley") $6=$6-1; print $1, $6, $7}' grade.txt


M.Tansley 39 44
J.Lulu 24 26
P.Bunny 35 28
J.Troll 26 26
L.Tansley 30 28
Modification des champs de texte

La modification des champs de texte est à nouveau une réaffectation du champ. Il suffit de donner au champ
une nouvelle valeur de chaîne. Pour ajouter l'initiale du milieu de J.Troll, afin que le nom devient J.L.Troll,
j'utilise l'expression «$ 1 =" J.L.Troll "», en pensant à placer la chaîne entre guillemets ("") et en fermant
chaque instruction entre parenthèses.

$ awk '{if($1=="J.Troll") ($1="J.L.Troll"); print $1}' grade.txt


M.Tansley
J.Lulu
P.Bunny
J.L.Troll
L.Tansley
Afficher uniquement l'enregistrement modifié

Les modifications de champ que nous avons apportées sont sur un petit fichier, donc imprimer tous les
enregistrements pour voir les modifications n'est pas vraiment un problème. Mais si vous avez un fichier
volumineux - disons plus de 100 enregistrements - vous ne voulez pas voir tous les enregistrements pour une
seule modification. Pour imprimer simplement l'enregistrement modifié, nous utilisons les accolades après
le motif, de sorte que nous obtenons «motif puis action en fonction du résultat du motif». Cela peut sembler
déroutant, alors voici le dernier exemple avec seulement l'enregistrement modifié imprimé. Notez la position
des accolades.

$awk '{if($1=="J.Troll") {$1="J.L.Troll";print $1}}' grade.txt


J.L.Troll
Création d'un nouveau champ de sortie
Lorsque vous traitez des données dans awk, c'est une bonne idée de créer occasionnellement un nouveau
champ lorsque vous effectuez des calculs basés sur d'autres champs. Un nouveau champ dans awk est créé
en attribuant la nouvelle identité de champ à partir d'une affectation d'autres champs. Pour créer un nouveau
champ basé sur l'ajout d'autres champs, vous pouvez taper «{$ 4 = $ 2 + $ 3}».

En supposant que les enregistrements contiennent trois champs, nous avons créé un nouveau champ, le
champ-4, qui contient le résultat de l'addition de «champ-2» et «champ-3».

Nous allons maintenant créer un nouveau champ «champ-8» qui contient la différence entre les «points
marqués jusqu'à présent» et les «points max disponibles» de notre fichier grade.txt. L'expression doit être
«{$ 8 = $ 7- $ 6}». Nous testons d’abord que le champ «points jusqu’à présent» est inférieur au «nombre
maximum de points disponibles» pour chaque élève, de sorte que le nouveau champ n’imprimera que les
noms pour lesquels il existe réellement une différence de valeur. Nous mettrons également un onglet dans la
partie BEGIN pour aligner les titres des rapports.

$ awk 'BEGIN{ print "Name\t Difference"}{if($6 <$7) {$8=$7--$6; print $1,$8}}'


grade.txt
Name Difference
M.Tansley 4
J.Lulu 2
Nous pourrions bien sûr rendre les nouveaux champs plus significatifs et leur attribuer un nom de variable,
comme ceci:

$ awk 'BEGIN{ print "Name\t Difference"}{if($6 <$7) {diff=$7-$6; print $1,diff}}'


grade.txt
M.Tansley 4
J.Lulu2

Ajout de colonnes
Pour ajouter des numéros de colonne ou exécuter des totaux, nous utilisons le signe +=. La variable qui
contient le résultat de l’ajout se trouve sur le côté gauche de l’égalité. Le champ que vous ajoutez ($1…ect)
à la variable va à droite de l’égalité. Pour ajouter $1 à une variable appelée ‘total’, nous
utiliserons ‘ total+=$1’. L'ajout de colonnes est très populaire : combien de fois avez-vous eu des fichiers
dans lesquels vous voulez ajouter les totaux ensemble, mais vous ne pouvez pas être déranges pour sortir la
calculatrice ? Dans awk, c’est simple, comme nous le verrons dans l’exemple suivant.
Pour ajouter tous les "points gagnés" de tous les étudiants, nous utilisons cette expression ‘ tot+=$6 ’,où tot
contiendra les résultats de l’ajout. Comme awk lit dans le fichier, nous mettrons un peu de fin a l’état de la
bande d’annonce dans la partie END qui imprimera le total lorsque tous les enregistrements auront été lus.

$ awk '(tot+=$6); END{print "Club student total points :" tot}'grade.txt


M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48Y yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansley 05/99 4712 Brown-2 12 30 28
Club student total points :155
Si un fichier est volumineux, vous pouvez simplement imprimer la partie de résultat et ne pas voir tous les
enregistrements. Pour ce faire, il vous suffit d’insérer les () entre les crochets à l’extérieur de l’instruction :

$ awk '{(tot+=$6)}; END{print "Club student total points :" tot}'grade.txt


Club student total points :155

Ajout de tailles de fichier

Lorsque je regarde des fichiers dans des répertoires, je veux pouvoir voir rapidement la taille totale de tous
mes types de fichiers, mais je veux exclure les sous-répertoires. Je peux le faire en redirigeant ls -l vers awk,
puis en utilisant awk pour exclure le premier caractère s’il s’agit d’un ‘d’ (en utilisant une expression
régulière). Je peux ensuite ajouter la colonne de taille de fichier, puis imprimer chaque fichier avec sa taille
et le total des tailles de fichier à la fin.Dans cet exemple, voici ce que mon ls -l apporte. Notez que le premier
caractère est un «d» sur le deuxième fichier, ce qui me dit qu'il s'agit d'un répertoire, la colonne de cette liste
pour la taille du fichier est la colonne 9 et les noms de fichiers sont la colonne 5. Vous devrez peut-être
changer ce numéro si votre système affiche les tailles / noms de fichiers dans une autre colonne,

-rw-r--r-- 1 root root 80 Apr 11 18:56 acc.txt

drwx------ 2 root root 1024 Mar 26 20:53 nsmail

Columns 1 23 4 5 6 7 8 9

L'expression régulière ci-dessous indique qu’elle doit commencer au début de la ligne ^, et exclure tout
caractère qui est un "d". Donc nous terminons avec ^[^d]. En utilisant ce modelé, nous pouvons imprimer
les noms de fichiers de leur taille, puis additionner chacune de ces tailles en plaçant le résultat dans la variable
‘tot’.

$ ls -l | awk ' /^[^d]/ {print $9"\t"$5} {tot+=$5} END {print "total KB:"tot}'
dev_pkg.fail 345
failedlogin 12416
messages 4260
sulog 12810
utmp 1856
wtmp 7104
total KB:41351
Chapitre 5 awk –fonctions intégrées

Fonctions de chaîne intégrées

Awk a quelques puissantes fonctions de chaîne. Tableau 5.4 listes de certaines d'entre eux.

La fonction gsub est un peu comme la recherche et le replacement de sed. Elle vous permettra de
substituer globalement un ou plusieurs caractères (r) à une ou plusieurs autres caractères (s). Cela se
fait avec l’utilisation d’expression régulière.

La première fonction est effectuée sur le record actuel $0. La deuxième fonction gsub vous permet de
spécifier la cible ; toutefois si vous ne spécifiez pas l’objectif, le remplacement est effectué sur $0.

Tableau 5.4. Awk ’s built-in string functions

gsub (r,s) Remplacer s par r globalement en $0

gsub (r,s,t) Remplacer s par r globalement en t

index (s,t) Retourne la première position de la chaîne t en s

length (s) Retourne la longeur de s

match (s,r) Tester si s contient une correspondance de sous-chaînes de r

split (s,a,fs) Fractionner s dans le tableau a sur fs

sprint (fmt,exp) Retourne l'exp formaté selon fmt

sub (r,s) Substitut s pour la sous-chaîne la plus longue de gauche de $0

substr (s,p) Retourn le suffix de s qui commence a p

substr (s,p,n) Retourner la sous-chaîne de s de longueur n commençant à p

La fonction index (s,t) retournera la première position de la chaîne de recherche (t) qui se trouve dans
la (les) chaine(s) cible(s). La fonction de longueur retournera le nombre total de caractères dans la (les)
chaines(s).
La fonction match vérifie si la chaine (s) contient une correspondance définie par l’expression
régulière e (r). La fonction de fractionnement divise la (les) chaines(s) en un tableau spécifié (a), en
utilisant le séparateur de champ fs.

La fonction sprint est comme la fonction printf (nous allons la rencontrer plus tard dans ce cours)

Il retournera la chaine de résultats (exp) basée sur la sortie formatée (fmt).

La fonction sub (r,s) remplacera (s) la sous-chaine la plus longue de gauche de $0 par (r).

La valeur de "valeur" (s,p) renvoie le suffixe de la chaine (s) commençant à la position (p) dans la
chaine.

Substr (s,p,n) est le même que ci-dessus, mais vous pouvez spécifier la longueur (n) de la sous-chaine.

Voyons comment certaines de ces fonctions de chaine fonctionnent dans awk.

gsubPour remplacer globalement une chaîne par une autre dans l'enregistrement actuel, nous devons ut
iliserle format d'expression régulière, " /target pattern/,replace pattern/".

Si nous voulions changerLe nombre d'étudiants de 4842 à 4899, nous pourrions faire ceci :

$ awk 'gsub(/4842/,4899) {print $0}' grade.txt


J.Troll 07/99 4899 Brown-3 12 26 26

Index
Pour rechercher la (les) chaine(s) cibles(s) pour la première occurrence de (t), nous insérons la chaine
entre guillemets. Pour savoir où la chaîne "ny" apparaît pour la première fois dans la chaine
cible "Bunny", renvoyant le nombre de caractères, nous pouvons faire ceci :

$ awk 'BEGIN {print index("Bunny","ny")}' grade.txt


4

Length

Pour retourner la longueur d'une chaîne, il suffit de fournir la chaîne. L’exemple suivant montre
comment vérifier que nous avons un "J.Troll" puis imprimer le nom et la longueur de la chaîne, en
retournant combien de caractères composent le nom de la personne.

$ awk '$1=="J.Troll" {print length($1)" "$1}' grade.txt


7 J.Troll
Match

Match vous permet de tester si la chaîne cible contient une partie de la chaîne de recherche.

Vous pouvez utiliser des expressions régulières si vous souhaitez dans la partie de recherche. Il
retournera un numéro où il a trouvé l’évènement s’il a réussi. Si aucune occurrence n’a été trouvée,
elle retournera un zéro. Le premier exemple teste si "d" est dans la chaine ANCD ; ce n’est pas le cas,
donc un zéro est retourné. Le deuxième exemple montre comment vérifier
si si "D" est dans la chaîne ANCD ; il est, et il retourne le nombre de caractères sur la première
occurrence. Le troisième exemple permet de vérifier l’occurrence de "u" dans l'étudiant "J.Lulu".

$ awk 'BEGIN {print match("ANCD",/d/)}'


0
$ awk 'BEGIN {print match("ANCD",/C/)}'
3
$ awk '$1=="J.Lulu" {print match($1,"u")}' grade.txt
4
Split

Vous pouvez utiliser split pour renvoyer le nombre d'éléments d'un tableau à partir d'une chaîne. Voici
comment ça marche. Si vous aviez une chaîne contenante, par exemple, des numéros de pièce séparés
par un tiret "-", comme ceci, AD2-KP9-JU2-P1, et que vous vouliez les mettre dans un tableau, en
utilisant la séparation, vous spécifiez le séparateur, et ce que le tableau doit être appelé.
Pour notre exemple de numéro de pièce, la commande serait fractionnée
("AD2-KP9-JU2-LP-1",parts_array,"-") et fractionnée retournerait alors le nombre d’index, dans ce
cas, il serait 4. Voici un autre exemple utilisant un séparateur différent.

$ awk 'BEGIN {printsplit("123#456#678", myarray, "#")}'


3

Sub
Utilisez sub pour rechercher et remplacer la première occurrence du motif. Si j’avais une chaine de
caractères appelee SRT contenant ‘poped popepill’ et que j’ai exécuté la sous-commande suivante
dessus : "sub(/op/,"OP", STR)", il n’atteindrait que la première occurrence du motif "op", le changerait
et retournerait la chaine suivante, "pOPed pill pape".
Dans notre fichier texte, le dossier de l’étudiant J.Troll a deux valeurs identiques, les "points gagnés"
et les "points max disponibles", qui sont tous deux fixés à 24. Pour changer seulement la première
occurrence de 24 à 29 et laisser la seconde intacte, vous pouvez effectuer cette
commande ‘sub (/26/, "29", $0) ’, qui n’atteindra que la première occurrence de 24.
Assurez-vous d’abord que nous avons le dossier de J.Troll.
$ awk '$1=="J.Troll" sub(/26/,"29",$0)' grade.txt
M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 29
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 29 26
L.Tansley 05/99 4712 Brown-2 12 30 28

Subtstr
Substr est une fonction utile. Elle retourne la partie de la chaîne que vous voulez retourner, en utilisant
la position de départ et la quantité de retour que vous voulez. Voici quelques exemples.

$ awk '$1=="L.Tansley" {printsubstr($1,1,5)}' grade.txt


L.Tan

Dans l'exemple ci-dessus, nous avons indiqué que nous voulons retourner les cinq premiers caractères
commençant au premier caractère à partir du champ-1. Si vous mettez une valeur dans la partie
"combien vous voulez retourner" et que ce nombre est beaucoup plus grand que la longueur réelle de
la chaine, awk retournera tous les caractères de la chaine, à partir du numéro de position que vous lui
avez donnée.
Pour extraire la partie de nom de famille de L.Tansley seulement, nous savons que nous devons
commencer à trois caractères et la longueur que je veux est de sept caractères. Mais en mettant 99
comme longueur, awk retournera toujours ce que nous voulons.

$ awk '$1=="L.Tansley" {print substr($1,3,99)}' grade.txt


Tansley

L'autre variante de type "courbe" est celle où la partie de la chaîne retournée est le suffixe, ou les
caractères après la position de départ. Vous fournissez la chaîne, puis juste la position de départ à
partir de laquelle vous voulez que la sous-chaîne soit retournée.
Pour obtenir uniquement les noms de famille à partir du fichier texte, je dois entrer les premiers
champs et commencer depuis le troisième caractère.

$ awk '{print substr($1,3)}' grade.txt


Tansley
Lulu
Bunny
Troll
Tansley
Voici un autre exemple, en utilisant une chaîne définie dans la partie BEGIN. Elle retourne ce qui reste
apres que sept caractères ont été coupes de la chaîne.

$ awk 'BEGIN {STR="A FEW GOOD MEN"}END{print substr(STR,7)}' grade.txt


GOOD MEN

Passage des chaînes de l'interpréteur de commandes à awk


J'ai dit au début de ce chapitre que beaucoup de commandes awk ne seront qu'une ligne, et quelques-
uns d'entre eux seront de la manipulation de chaînes de caractères.Vous ferez ces lignes de votre script
au fur et à mesure que nous progresserons dans ce chapitre.
Pour vous montrer à quel point il est facile de faire des lignes simples qui transmettent des variables
à une ligne de commande awk, voici quelque exemple avec une brève explication pour chacune
d’elles. Fait echo à la chaîne " Stand-by ", à l'aide d'un tube avec awk et retourne la longueur de
celle-ci :

$ echo "Stand-by" |awk '{print length($0)}'


8
Attribuez à la variable STR un nom de fichier, un tube à awk pour renvoyez le nom de fichier sans
extension.

$ STR="mydoc.txt"
$ echo $STR| awk '{print substr($STR,1,5)}'
mydoc

Attribuez à la variable STR un nom de fichier, un tube à awk pour renvoyez uniquement l'extension du
nom de fichier :

$ STR="mydoc.txt"
$ echo $STR| awk '{print substr($STR,7)}'
txt
Séquences d'échappement de chaîne
Lorsque vous utilisez des chaînes ou des expressions régulières, vous pouvez inclure une nouvelle
ligne dans la sortie ou rechercher un metacaractère.
Lors de l'impression d'une nouvelle ligne (une nouvelle ligne est le caractère \n), nous lui donnons une
séquence d’échappement, pour qu’awk n’interprète pas mal le sens. On peut y échapper en lui donnant
une signification spéciale en mettant une barre oblique inverse. Par exemple pour forcer awk
à imprimer une nouvelle ligne nous utilisons \n. Si vous utilisez des expressions régulières et que vous
voulez rechercher le crochet de courbe ({), il vous suffit de placer la barre oblique inverse avant le
caractère, comme " /\{/". Ceci désactivera la signification spéciale que le support a dans awk. Il y a
d’autres séquence d’échappement reconnues par awk, et celles-ci sont indiquées dans le tableau 5.5.

Tableau5.5. Séquences d'échappement que vous pouvez utiliser avec awk

\b Backspace Retour arrière

\f Formfeed flux de formulaire

\n Nouvelle ligne

\r Retour chariot

\t Tab

\ddd Valeur octale

\c Tout autre caractère spécial. Par exemple, \\ signifie un signe barre oblique inverse.

Nous imprimerons May Day, avec un onglet entre May et Day, suivi de deux nouvelles lignes, puis
imprimerons May à nouveau, puis imprimerons Day à nouveau, mais cette fois en utilisant les
numéros octaux. 104, 141, 171 pour D, a, y respectivement.

$ awk 'BEGIN {print"\n\May\tDay\n\nMay \104\141\171"}'


May Day
May Day

Note : \104 est le numéro de référence de l'ASCII D, \141 est le numéro de référence de l'ASCII a, etc.
Fonctions de sortie awk (printf)

Tous nos exemples concernant la sortie jusqu'à présent viennent d'être imprimés à l'écran, sans aucun
format, à l'exception de l'onglet. Awk fournit plusieurs options dans une fonction appelée printf, qui
vous permettent de formater la sortie de plusieurs manières différentes. Par exemple, vous pouvez
avoir une sortie de colonne fixe et une justification à droite et à gauche. Chaque fonction printf
(caractère de contrôle de format) commence par un signe % et se termine par un caractère qui
détermine la conversion. La conversion peut contenir trois modificateurs. La syntaxe de base pour
utiliser la fonction printf est printf ([spécificateur de contrôle de format], arguments).

Modificateurs printf

Tableau 5.6. Modificateurs de printf

- Justifier à gauche

Width Remplissez le champ au besoin, entraînant 0 tampon avec des zéros

.prec Largeur de chaîne maximale ou chiffres à droite du séparateur décimal

Spécificateurs de caractères de contrôle du format printf

Tableau 5.7. Format d'affichage

%c Caractère ASCII

%d Entier décimal

%e Nombre à virgule flottante - scientifique

%f Numéro à virgule flottante, c'est-à-dire (123,44)

%g Laissez awk décider quelle conversion à virgule flottante utiliser, e ou f

%o Numéro octal non signé

%s Chaîne contenant des caractères

%x Nombre hexadécimal non signé

Conversion de caractères
Pour voir l'équivalent de 65 en ASCII, vous pouvez diriger le nombre 65 vers awk. printf effectue
ensuite la conversion en caractère ASCII. J'ai également ajouté une nouvelle ligne. En effet, printf ne
met pas de nouvelle ligne pour vous par défaut.

$ echo "65" | awk '{printf "%c\n",$0}'


A

On aurait pu utiliser awk de cette façon, ce qui produit le même résultat :

$ awk 'BEGIN {printf "%c\n",65}'


A

Le format de toutes les conversions de caractères est le même. Ici, nous voyons à quoi ressemble
«999» lorsque nous utilisons la conversion en virgule flottante. Il passe à six décimales lorsqu'un
entier lui est transmis.

$ awk 'BEGIN {printf "%f\n",999}


999.000000

Sortie formatée
Pour imprimer les noms des étudiants et leurs numéros de série, je veux que les noms soient laissés
justifiés ; la chaîne qui les imprime comportera 15 caractères, suivis des numéros de série. Notez que
le \ n fil de nouvelle ligne est placé après le dernier spécificateur. Cette sortie alignera
automatiquement les deux colonnes,

$ awk {printf "%-15s %s\n", $1,$3}' grade.txt


M.Tansley 48311
J.Lulu 48317
P.Bunny 48
J.Troll 4842
L.Tansley 4712

Ce serait bien d'avoir un texte expliquant de quel type de rapport il s'agit, alors collons un en-tête.
Vous remarquerez que nous utilisons l'impression pour l'en-tête, mais nous aurions pu utiliser printf si
nous le voulions.
$ awk 'BEGIN {print "Name \t\tS.Number"}{printf "%-15s %s\n", $1,$3}'
grade.txt
Passer des valeurs aux awk one-liners
Avant d'examiner les scripts awk, voyons d'abord comment passer des variables à awk sur la ligne de
commande.Lorsque vous voulez donner une valeur à une variable awk avant l'appel de awk, vous
mettez la variable sur la ligne de commande. Le format général pour cela est :
commandes awk var = valeur fichier d'entrée (Nous découvrirons plus tard comment passer des
variables aux scripts awk.)
Ici, nous définissons la variable AGE sur 10 sur la ligne de commande. Il est ensuite passé à awk, pour
voir quels élèves ont moins de 10 ans.
$ awk '{if ($5 < AGE) print $0}' AGE=10 grade.txt
M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26

Pour vérifier rapidement l'espace sur mon système de fichiers et voir s'il a atteint un certain niveau,
j'utilise une awk one-liner. Étant donné que la quantité d'espace utilisé que je souhaite surveiller peut
changer, vous pouvez spécifier cette valeur de déclenchement sur la ligne de commande.
Je redirige df -k vers awk, puis récupère la colonne 4 qui est l'espace disponible ou libre ; Je m'assure
de n'obtenir que les nombres (1024 blocs) et non les en-têtes de texte de df en utilisant '$ 4~ / ^ [0-9] /',
puis je fais un test par rapport à la valeur que nous avons précédemment spécifiée sur la ligne de
commande ' if ($ 4 <TRIGGER) 'qui est défini sur la variable TRIGGER.

$ df -k | awk '($4 ∼/^[0-9]/) {if($4 < TRIGGER) print $6"\t"$4}'


TRIGGER=56000
/dos 55808
/apps 51022

Voici les numéros de colonne, lorsque j'utilise df -k sur le système que j'administre.

Filesystem 1024-blocks Used Free %Used Mounted on

colonne 1 2 3 4 5 6

Vous devrez peut-être modifier les numéros de colonne pour que la commande fonctionne sur votre
système, si df signale différents formats de rapport.

Vous pouvez bien sûr utiliser un pipe pour envoyer des valeurs via awk. Ici, nous utilisons la
commande who: la première colonne de la commande who contient toujours les noms d'utilisateurs qui
sont connectés, donc nous l'imprimons simplement avec un message.
$ who | awk '{print $1 " is logged on"}'
louisel is logged on
papam is logged on

Awk vous permet également de transmettre des variables d'environnement. L'exemple suivant utilise
la variable d'environnement LOGNAME, qui contient votre nom de connexion et imprime un
message. Ces informations sont obtenues en redirigeant la sortie de la commande who vers awk.

$ who | awk '{if ($1 == user) print $1" you are connected to
"$2}'user=$LOGNAME
Voici la sortie, si root est bien connecté.
root you are connected to ttyp1

Fichier de script awk

Vous pouvez coller n'importe quelle commande awk dans un fichier et l'exécuter. Les commandes ne
doivent pas être longues, bien que ce soit généralement la raison pour laquelle vous les placez dans un
fichier script. Il est tout à fait acceptable d'avoir des lignes simples dans un fichier de script, après tout,
cela vous évite de retaper la commande chaque fois que vous souhaitez l'utiliser. L’autre avantage de
l’utilisation d’un fichier est que vous pouvez y ajouter des commentaires afin de ne pas oublier ce que
fait réellement le programme et à quoi il sert.
Nous allons utiliser l'un de nos exemples précédents et le convertir en un fichier de script exécutable
awk. En voici un que nous avons fait plus tôt. Il additionne les colonnes des points des étudiants
gagnés lors des compétitions.

awk '(tot + = 6 $); END {print "Total des points des étudiants du club:" tot} 'grade.txt.

Créons un nouveau fichier et appelons-le student_tot.awk - c'est toujours une bonne idée de donner à
tous les programmes awk une extension awk, donc vous savez que c'est un programme awk rien qu'en
regardant le nom du fichier.

Tapez maintenant ce qui suit.


!/bin/awk -f
# all comment lines must start with a hash ‘#’
# name: student_tot.awk
# to call: student_tot.awk grade.txt
# prints total and average of club student points

#print a header first


BEGIN{
print "Student Date Member No. Grade Age Points Max"
print "Name Joined Gained Point Available"
print "=================================================================="

}
# let’s add the scores of points gained
(tot+=$6)
# finished processing now let’s print the total and average point
END{print "Club student total points :" tot
print "Average Club Student points:" tot/NR}

La première ligne contient ! /bin/awk -f. Ceci est important - sans cette ligne, le script autonome ne
s'exécutera pas. La ligne indique au script où trouver awk sur le système. Vous pouvez voir qu'en
espaçant les commandes, il est beaucoup plus facile à lire, et vous pouvez également avoir des lignes
vides entre vos commandes. J'ai ajouté un en-tête et un score moyen à la fin, mais en substance, il
s'agit d'une ligne unique insérée dans un fichier.Lorsque nous exécutons le script, nous fournissons le
fichier d'entrée après le nom du script, mais nous devons d'abord donner au fichier de script
l'autorisation d'exécution.

$ chmod u+x student_tot.awk


$ student_tot.awk grade.txt
Student Date Member No. Grade Age Points Max
Name Joined Gained Point Available
===================================================================
M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48Y ellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansley 05/99 4712 Brown-2 12 30 28
Club student total points :155
Average Club Student points:31
Un programme de vérification des comptes qui s'exécute sur l'un de nos systèmes vérifie la saisie des
données par les opérateurs de données. Malheureusement, il y a un petit bug dans ce programme, ou
devrions-nous dire «une fonctionnalité non documentée», où si un enregistrement contient une erreur,
il ne devrait imprimer la ligne «ERREUR *» qu'une seule fois. Mais il semble vouloir imprimer
plusieurs fois la ligne d'erreur. Cela irrite les gens des comptes, alors voici un script awk qui filtre les
nombreuses occurrences de la ligne d'erreur afin qu'il n'y ait qu'une seule ligne d'erreur par
enregistrement en échec.
Voici à quoi ressemble le fichier avant qu'awk effectue son filtrage.
...
...
INVALID LCSD 98GJ23
ERROR*
ERROR*
CAUTION LPSS ERROR ON ACC NO.
ERROR*
ERROR*
ERROR*
ERROR*
ERROR*
PASS FIELD INVALID ON LDPS
ERROR*
ERROR*
PASS FIELD INVALID ON GHSI
ERROR*
CAUTION LPSS ERROR ON ACC NO.
ERROR*
ERROR*

Voici le script awk qui effectue le filtrage.

#!/bin/awk -f
# error_strip.awk
# to call: error_strip.awk<filename>
# strips out the ERROR* lines if there are more than one
# ERROR* lines after each failed record.

BEGIN { error_line="" }
# tell awk the whole is "ERROR*"
{ if ($0 == "ERROR*" &&error_line == "ERROR*")

# go to next line
next;
error_line = $0; print }

Et voici la sortie après l'avoir filtrée par awk:


$ strip.awk strip
INVALID LCSD 98GJ23
ERROR*
CAUTION LPSS ERROR ON ACC NO.
ERROR*
PASS FIELD INVALID ON LDPS
ERROR*
PASS FIELD INVALID ON GHSI
ERROR*
CAUTION LPSS ERROR ON ACC NO.
ERROR*

Utilisation de la variable FS dans les scripts awk


Si vous analysez un fichier qui a un espace non comme séparateur de champ (FS), comme un # ou un :
faire des lignes simples est facile parce que vous pouvez spécifier le FS sur la ligne de commande
comme ceci :

$ awk -F: 'awk {print $0}' input-file

Lorsque vous utilisez des scripts awk, n'oubliez pas de toujours mettre la variable FS dans la partie
BEGIN. Si vous ne vous trompez pas, vous serez confus et vous ne saurez pas quel est le séparateur de
champ. Voici un bref script sur la façon de spécifier la variable FS. Le script extrait simplement les
premier et cinquième champs du fichier / etc / passwd; les champs du fichier passwd sont séparés par
deux points (:); le premier champ est le nom de connexion et le cinquième est le titulaire du nom du
compte.

$ cat passwd.awk
!/bin/awk -f
# to call: passwd.awk /etc/passwd
# print out the first and fifth fields
BEGIN{
FS=":"}
{print $1,"\t",$5}
$ passwd.awk /etc/passwd
root Special Admin login
xdm Restart xdm Login
sysadm Regular Admin login
daemon Daemon Login for daemons needing permissions
Passer des valeurs aux scripts awk
La transmission de valeurs aux scripts awk se fait de la même manière que lorsque nous transmettons
des valeurs à des lignes individuelles. Le format est :
awk script-file var = valeur fichier d'entrée
Le petit script suivant vérifiera le nombre de champs dans un fichier par rapport au nombre que vous
lui fournissez, une petite vérification soignée utilisant la variable NF. MAX contient les numéros de
champ que vous souhaitez vérifier. Utilisez des guillemets doubles pour entourer le séparateur de
champ même s'il s'agit d'un espace.
$ cat fieldcheck.awk
#!/bin/awk -f
# check on how many fields in a file
# name:fieldcheck.awk
# to call: fieldcheck MAX=n FS=<separator> filename
#
NF!=MAX{
print("line " NR " does not have" MAX " fields")}

Si on voulait l'exécuter avec le fichier / etc / passwd (le fichier passwd a sept champs), on donnerait les
paramètres suivants:

$ fieldcheck.awk MAX=7 FS=":" /etc/passwd

En utilisant l’exemple précédent à une ligne, nous le convertirons en un script awk.


$ cat name.awk
#!/bin/awk -f
# name: age.awk
# to call: age.awk AGE=n grade.txt
# prints ages that are lower than the age supplied on the comand line
{if ($5 < AGE)
print $0}

Mes commentaires occupent plus que les commandes réelles, mais cela n'a pas d’importance ; en
regardant ces commentaires, je sais exactement ce qu'il fait et comment l'appeler. N’oubliez pas de
rendre le script exécutable pour vous-même, puis exécutez-le en plaçant la variable et sa valeur sur la
ligne de commande après le nom du script, mais avant le fichier d'entrée.

$ age.awk AGE=10 grade.txt


M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
Vous pouvez également transmettre des valeurs à l'aide de la commande pipe comme nous l'avons
découvert précédemment. Voici un script awk qui prend la sortie de la commande du et présente la
sortie en bytes et en blocs .
$ cat duawk.awk
#!/bin/awk -f
# to call: du | duawk.awk
# prints file/direc's in bytes and blocks
BEGIN{
OFS="\t" ;
print "name" "\t\t","bytes","blocks\n"
print "=============================="}
{print $2,"\t\t",$1*512,$1}

Pour exécuter ce script, utilisez simplement la commande du et dirigez-le vers le script awk.

$ du | duawk.awk
name bytes blocks
=========================================
./profile.d 2048 4
./X11 135680 265
./rc.d/init.d 27136 53
./rc.d/rc0.d 512 1
./rc.d/rc1.d 512 1

Tableaux awk

Lorsque nous avons couvert la fonction de division plus tôt, nous avons vu comment elle pouvait être
utilisée pour charger des éléments dans des tableaux. Voici encore cet exemple

$ awk 'BEGIN {print split("123#456#678", myarray, "#")}'


3
Dans l'exemple précédent, split renvoie le nombre d'index pour le tableau appelé myarray. Le tableau
myarray ressemblerait alors à ceci en interne.
Myarray[1]="123"
Myarray[2]="456"
Myarray[3]="678"

Lorsque vous utilisez des tableaux, ils n'ont pas besoin d'être déclarés au préalable ni de spécifier le
nombre d'éléments dans le tableau. Pour accéder à un tableau, la boucle for est généralement utilisée.
Voici la construction de base de l'un des types de boucles for :
for (element in array) print array[element]).

En utilisant notre exemple d'enregistrement "123 # 456 # 678", utilisons à nouveau la fonction split
pour le charger, puis utilisons une boucle for pour l'imprimer. Voici le script qui effectue le
chargement et l’impression :

$ cat arraytest.awk
#!/bin/awk -f
# name: arraytest.awk
# prints out an array
BEGIN{
record="123#456#789";
split(record, myarray,"#") }
END { for (i in myarray) {print myarray[i]}}

Pour exécuter le script, nous utilisons / dev/null comme fichier d'entrée. Cela incite à penser qu'il a un
fichier d’entrée ; si nous ne le faisions pas, nous resterions là et attendrions notre entrée.

$ arraytest.awk /dev/null
123
456
789

Tableaux et enregistrements

L'exemple ci-dessus vous a montré comment utiliser des tableaux à l'aide de la fonction de
fractionnement, mais vous pouvez également prédéfinir un tableau et utiliser ce tableau pour tester des
champs. Dans l'exemple suivant, une utilisation plus courante des tableaux est illustrée.
Vous trouverez ci-dessous une partie d'un téléchargement de la base de données de karaté contenant
les notes des étudiants et s'ils sont adultes ou juniors. Il n'y a que deux champs et le séparateur de
champ est le symbole de hachage (#).

Voici le fichier:
$ cat grade_student.txt
Yellow#Junior
Orange#Senior
Yellow#Junior
Purple#Junior
Brown-2#Junior
White#Senior
Orange#Senior
Red#Junior
Brown-2#Senior
Yellow#Senior
Red#Junior
Blue#Senior
Green#Senior
Purple#Junior
White#Junior

Notre tâche consiste à lire le fichier et à afficher les informations suivantes.


✓ Combien de catégories de ceinture jaune, orange et rouge il y a dans le club.
✓ Combien de juniors et seniors y a-t-il dans le club.
En regardant le fichier texte, vous pourriez probablement deviner la réponse dans environ 30 secondes.
Mais qu'en est-il si je vous dis que le fichier complet comporte plus de 60 enregistrements ? Ce n'est
pas si facile maintenant ? Eh bien, c'est avec awk.

$ cat belts.awk
!/bin/awk -f
# name: belts.awk
# to call: belts.awk grade2.txt
# loops through the grade2.txt file and counts how many
# belts we have in (yellow, orange, red)
# also count how many adults and juniors we have
#
# start of BEGIN
# set FS and load the arrays with our values
BEGIN{FS="#"
# load the belt colours we are interested in only
belt["Yellow"]
belt["Orange"]
belt["Red"]
# end of BEGIN
# load the student type
student["Junior"]
student["Senior"]
}
# loop thru array that holds the belt colours against field-1
# if we have a match, keep a running total
{for (colour in belt)
{if ($1==colour)
belt[colour]++}}
# loop thru array that holds the student type against
# field-2 if we have a match, keep a running total
{for (senior_or_junior in student)
{if ($2==senior_or_junior)
student[senior_or_junior]++}}
# finished processing so print out the matches..for each array
END{ for (colour in belt) print "The club has", belt[colour], colour,
"Belts"

for (senior_or_junior in student) print "The club has",


student[senior_or_junior]\,senior_or_junior, "students"}

La partie BEGIN définit le FS sur le hash #, qui est notre séparateur de champ, car nous voulons
trouver les ceintures (jaune, orange et rouge). Nous avons ensuite configuré manuellement l'index du
tableau dans le script, et il en va de même pour l'étudiant. Notez à ce stade ce sont les indices ou les
éléments ; nous n'ajoutons pas encore de référence au nom du tableau lui-même. Toutes nos
initialisations sont terminées, donc c'est la fin de BEGIN. N'oubliez pas qu'aucun traitement de fichier
n'est effectué dans la partie BEGIN.
Nous pouvons maintenant traiter le fichier. Ici, nous donnons au tableau son nom de «couleur» et
utilisons une boucle for pour tester si le champ-1 (c'est-à-dire la colonne des ceintures) est égal à l'un
des éléments de «couleur» du tableau (jaune, orange ou rouge). S'il existe une correspondance,
conservez un total cumulé dans le tableau par rapport à chaque élément correspondant.
Le même processus est ensuite effectué sur le tableau ‘senior_or_junior’. Si une correspondance est
trouvée lors de la numérisation du champ 2, un total cumulé est conservé sur les éléments de tableau
correspondants de junior ou senior.
La partie END se charge d'imprimer les résultats de la numérisation. Ici, une boucle for est utilisée
pour parcourir chaque tableau et les imprimer.
Vous remarquerez une barre oblique inverse "\" à la fin de l'une des instructions d'impression. Ceci est
utilisé pour dire à awk (ou à n'importe quel script d'ailleurs) que la commande continue sur la ligne
suivante. Ceci est utilisé lorsque vous avez une longue commande unique et que vous souhaitez la
diviser en quelques lignes.

Avant d'exécuter le script, n'oubliez pas de le rendre exécutable.


$ belts.awk grade_student.txt
The club has 2 Red Belts
The club has 2 Orange Belts
The club has 3 Yellow Belts
The club has 7 Senior students
The club has 8 Junior students

CONCLUSION

Le langage awk peut être un langage complexe à apprendre, mais pour l'utiliser pour des lignes

simples ou de petits scripts, la courbe d'apprentissage n'est pas très abrupte. Tout au long de ce

chapitre, j'ai essayé de vous présenter awk à son niveau le plus basique.

Je ne suis pas entré dans la langue awk trop en profondeur ; Je crois que nous avons couvert l'essentiel

pour awk. Awk est un outil important dans la programmation shell, mais vous n'avez pas besoin d'être

un gourou pour utiliser ses puissantes capacités de traitement de texte, dans le shell ou avec des

programmes shell.

Vous aimerez peut-être aussi