Académique Documents
Professionnel Documents
Culture Documents
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:
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 :
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.
<Champ-1> <sep> <Champ-2> <sep> <Champ-3> <sep> <Champ-4 and nouvelle ligne>
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.
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
$ belts.awk grade_student.txt
Mais nous pouvons utiliser l'un des éléments suivants à la place.En utilisant un peu de redirection :
$ cat grade2.txt|belts.awk
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
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:
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.
Operateur Description
< Lessthan
== Equal to
!= Not equal to
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.
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
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
&& 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
AND (ET)
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 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.
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
|| && ! OU, ET, NON (nous avons traité de ces questions dans la dernière section)
∼ !∼ Opérateurs de correspondance, correspondance et non-correspondance
+ + -- 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.
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.
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
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.
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.
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.
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.
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,
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
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.
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)
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.
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 :
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 :
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.
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".
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.
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.
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.
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.
$ 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.
\n Nouvelle ligne
\r Retour chariot
\t Tab
\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.
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
- Justifier à gauche
%c Caractère ASCII
%d Entier décimal
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.
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.
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,
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.
Voici les numéros de colonne, lorsque j'utilise df -k sur le système que j'administre.
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
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.
}
# 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.
#!/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 }
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:
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.
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
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
$ 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"
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.
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.