talking about awk

This commit is contained in:
tTh 2024-09-17 18:53:54 +02:00
parent 5723a754a8
commit 02054433b4
1 changed files with 110 additions and 5 deletions

View File

@ -1,7 +1,28 @@
\chapter{scripting}
XXX
Qu'est-ce que le \textsl{scripting} ?
C'est l'art de coller entre eux divers outils logiciels
afin de réaliser une tache donnée.
Le "collage" est fait par un \textbf{script},
lequel est un fichier texte, écrit dans divers
langages (plus ou moins spécifiques) et qui sera lu et exécuté
par un interpréteur.
Je ne vais pas revenir sur l'art du shebang, si vous ne
le connaissez pas, c'est expliqué page \pageref{shebang}.
En bref, c'est la manière dont le script sélectionne
le bon interpréteur lors de son lancement.
Quels sont les langages courrament utilisés pour faire du
script ? Il y a une bonne poignée de réponses à ça.
La première étant souvent « Use The Shell ! »,
et la seconde « tu as songé à awk ? »,
ce qui est tout aussi sensé.
Le shell étant dégrossi page \pageref{chap:shell},
passons directement au langage Awk.
% ===============================================================
\section{Awk} \index{Awk}
Awk est un langage de programmation crée
@ -45,7 +66,7 @@ des espaces et/ou des tabulations.
Ces données sont les coordonnées \textsc{x,y,z} et le rayon d'une
petite collection de bubulles. Pratiquement, une représentation
sommaire d'une sphère de povray\footnote{SDL keyword: \texttt{sphere}}.
sommaire d'une sphère de povray.
Le fichier à générer est en trois partie : l'en-tête, la liste
des bubulles\index{bubulle} et l'en-pied, ce qui est bien raccord
@ -63,21 +84,26 @@ deux d'entre eux étant précédés d'une « instruction ».
Le premier bloc, avec le mot-clef \textsc{BEGIN}, est exécuté
avant la lecture de la première ligne des données en entrée.
Ce qui est le bon moment pour initialiser des variables.
Nous l'utilisons pour créer l'en-tête d'un descripteur
d'objet pour Povray.
Le second bloc (sans label) est exécuté pour chaque ligne lue.
Et c'est ici que nous trouverons la magie.
La ligne lue depuis l'entrée a été découpée selon le
séparateur FS, et les tranches sont connues sous les noms
de \$1, \$2, ... \$N (la ligne entière étant \$0)
que nous utilisons dans la génération de la bubulle.
Et le troisième bloc (\textsc{END}) sera exécuté à la fin, après
la lecture et le traitement du dernier enregistrement,
qui sera dans notre cas la dernière ligne.
qui est dans notre cas la dernière ligne.
Et à l'exécution~:
\begin{verbatim}
tth@redlady:~/Devel/TetaTricks/code/awk$ ./mkunion.awk < dataset
#declare Bubules = object
#declare Bubulles = object
{
union {
sphere { <17.000000, 9.000000, 4.000000>, 1.500000 }
@ -85,14 +111,93 @@ union {
sphere { <0.000000, 0.000000, 0.000000>, 1.000000 }
}
}
// 3 bubulles
\end{verbatim}
% ===============================================================
\subsection{Mais ce n'est pas tout !}
% XXX to be continued XXX
Ce premier exemple nous a montré comment, avec quelques
lignes de code facile à comprendre, transformer des
données et faire quelques calculs avec ces données.
Nous avons vu le découpage de la ligne d'entrée, mais
ce n'est pas tout, je suis passé très vite sur ce sont
ces "labels" dont j'ai parlé.
Ce ne sont absolument pas des labels, ni des mot-clefs,
mais quelque chose de bien plus puissant.
C'est le mécanisme qui permet de sélectionner les lignes
sur lesquelles nous voulons appliquer un traitement.
Nous avons déja vu \textsc{BEGIN} et \textsc{END},
pour lancer du code avant-le-début et/ou après-la-fin.
Mais nous pouvons mettre des bouts de code donnant un résultat
booléen, oui/non, qui conditionnera l'exécution du
bloc de code ainsi
préfixé\footnote{J'ai l'impression de pas être très clair ?},
ce qui nous donnera des possibilités de filtrage
surpuissantes.
Par exemple, nous ne voulons pas de bubulle trop
petite, il suffit de précéder le second bloc de l'exemple
déja vu par un test sur la taille qui est dans
le quatrième champ du fichier d'entrée~:
\begin{verbatim}
$4 > 0.999 {
printf(" sphere { <%f, %f, %f>, %f }\n", \
$1, $2, $3, $4 )
}
\end{verbatim}
Vous comprenez maintenant les deux plus importantes choses
que l'on peut trouver dans Awk (/me fan).
XXX to be continued \index{XXX}
% ===============================================================
\subsection{Définir une fonction}
Bien, nous savons maintenant générer des bubulles avec un
filtrage sur la taille, mais nous voudrions maintenant procéder
à des calculs sur les données que nous lisons.
Deux choix s'offrent à nous, soit faire ça directement dans
le deuxième bloc, soit utiliser un sous-programme dédié.
Pour des raisons aussi bien didactiques que de bon sens,
nous allons opter pour la seconde solution.
Mais voyons d'abord la syntaxe d'une fonction, avec en prime
une petite astuce: si vous voulez utiliser Awk dans devoir
lui fournir de données en entrée, c'est simple, mettez tout
dans le bloc \textsc{BEGIN}.
\lstinputlisting[]{code/awk/demo-func.awk}
\begin{verbatim}
tth@redlady:~/Devel/TetaTricks/code/awk$ ./demo-func.awk
---- demo fonction ----
sin(1.000000) = 0.841471
distance from center = 0.707107
\end{verbatim}
La deuxième fonction demande quelques explications, puisqu'elle
met en œuvre un « awkisme » de bon aloi.
En effet, Awk ne connait pas les variables locales à une fonction,
c'est-à-dire connues seulement à l'intérieur de celle-ci.
% ===============================================================
\subsection{Les variables}
Et puisque on en parle...
% ===============================================================
\subsection{Pattern filtering} \index{pattern}
Wesh, regexp.
% ===============================================================