public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] gentoo commit in xml/htdocs/doc/fr/articles: l-awk3.xml
@ 2008-11-14 13:07 Marion Age (titefleur)
  0 siblings, 0 replies; only message in thread
From: Marion Age (titefleur) @ 2008-11-14 13:07 UTC (permalink / raw
  To: gentoo-commits

titefleur    08/11/14 13:07:41

  Added:                l-awk3.xml
  Log:
  #242486 New translation: /doc/fr/articles/l-awk3.xml thanks to Christophe LEFEBVRE

Revision  Changes    Path
1.1                  xml/htdocs/doc/fr/articles/l-awk3.xml

file : http://sources.gentoo.org/viewcvs.py/gentoo/xml/htdocs/doc/fr/articles/l-awk3.xml?rev=1.1&view=markup
plain: http://sources.gentoo.org/viewcvs.py/gentoo/xml/htdocs/doc/fr/articles/l-awk3.xml?rev=1.1&content-type=text/plain

Index: l-awk3.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<!-- $Header: /var/cvsroot/gentoo/xml/htdocs/doc/fr/articles/l-awk3.xml,v 1.1 2008/11/14 13:07:41 titefleur Exp $ -->
<!DOCTYPE guide SYSTEM "/dtd/guide.dtd">

<guide link="/doc/fr/articles/l-awk3.xml" lang="fr" disclaimer="articles">
<title>Awk par l'exemple, 3e partie</title>

<author title="Auteur">
  <mail link="drobbins@gentoo.org">Daniel Robbins</mail>
</author>
<author title="Traducteur">
  <mail link="clefebvre.62@free.fr">Christophe Lefebvre</mail>
</author>

<abstract>
Pour conclure cette série d'articles sur Awk, Daniel vous présente des
fonctions de chaînes de caractères importantes et va vous expliquer
complètement comment écrire un programme de suivi de compte à partir de zéro. À
cet effet, vous apprendrez comment écrire vos propres fonctions et comment
utiliser des tableaux Awk à plusieurs dimensions. À la fin de cet article, vous
aurez encore plus d'expérience en Awk, ce qui vous permettra de créer des
scripts plus avancés.
</abstract>

<!-- The original version of this article was published on IBM developerWorks,
and is property of Westtech Information Services. This document is an updated
version of the original article, and contains various improvements made by the
Gentoo Linux Documentation team -->

<version>1.4</version>
<date>2005-10-31</date>

<chapter>
<title>Fonctions de chaînes de caractères et... livre de tenue de comptes&nbsp;?
</title>
<section>
<title>Formater l'affichage du résultat</title>
<body>

<p>
Bien que la directive d'affichage «&nbsp;print&nbsp;» d'Awk fait généralement
son travail correctement, il est possible que nous ayons besoin d'encore mieux
dans certains cas. Pour ces situations, Awk offre deux bons vieux amis appelés
«&nbsp;printf()&nbsp;» et «&nbsp;sprintf()&nbsp;». Oui, ces fonctions comme
beaucoup d'autres d'Awk, sont identiques à leurs homologues en C.
«&nbsp;printf()&nbsp;» affiche une chaîne de caractères formatée, tandis que
«&nbsp;sprintf()&nbsp;» retourne une chaîne de caractères qui peut être
affectée à une variable. Si vous n'êtes pas familier avec
«&nbsp;printf()&nbsp;» et «&nbsp;sprintf()&nbsp;», un guide d'introduction au langage
C vous présentera rapidement ces deux fonctions essentielles d'affichage. Vous
pouvez voir la page du manuel de «&nbsp;printf()&nbsp;» en tapant <c>man 3
printf</c> sur votre système Linux.
</p>

<p>
Voici quelques exemples de code utilisant les fonctions «&nbsp;sprintf()&nbsp;»
et «&nbsp;printf()&nbsp;» d'Awk. Comme vous pouvez le voir, cela ressemble
beaucoup au C&nbsp;:
</p>

<pre caption="Exemple de code Awk avec «&nbsp;sprintf()&nbsp;» et
«&nbsp;printf()&nbsp;»">
x=1
b="foo"
printf("%s a eu %d à son dernier devoir\n","Jim",83)
myout=("%s-%d",b,x)
print myout
</pre>

<p>
Ce code affichera&nbsp;:
</p>

<pre caption="Résultat affiché par le code">
Jim a eu 83 à son dernier devoir
foo-1
</pre>

</body>
</section>
<section>
<title>Fonctions de chaînes de caractères</title>
<body>

<p>
Awk a une pléthore de fonctions de chaînes de caractères et c'est une bonne
chose. Dans Awk, les fonctions de traitement des chaînes de caractères sont
vraiment importantes puisque vous ne pouvez pas traiter une chaîne comme un
tableau de caractères comme dans d'autres langages tels que le C, le C++ et
Python. Par exemple, si vous exécutez le code suivant&nbsp;:
</p>

<pre caption="Exemple de code">
mystring="How are you doing today?"
print mystring[3]
</pre>

<p>
Vous aurez une erreur qui ressemblera à quelque chose comme ça&nbsp;:
</p>

<pre caption="Erreur générée par l'exemple de code">
awk: string.gawk:59: fatal: attempt to use scalar as array
</pre>

<p>
Oh, d'accord. Bien que pas aussi pratiques que les fonctions de type itérable
en Python, les fonctions Awk de chaînes de caractères font leur travail.
Jetons-y coup d'œil.
</p>

<p>
Tout d'abord, nous avons la fonction classique «&nbsp;length()&nbsp;» qui
retourne la longueur d'une chaîne de caractères. Voici comment vous pouvez
l'utiliser&nbsp;:
</p>

<pre caption="Exemple de la fonction length()">
print length(mystring)
</pre>

<p>
Ce code va afficher la valeur&nbsp;:
</p>

<pre caption="Valeur affichée">
24
</pre>

<p>
Bien, continuons. La prochaine fonction de chaînes de caractères est appelée
«&nbsp;index()&nbsp;» et retourne la position de l'occurrence d'une sous-chaîne
de caractères dans une autre chaîne de caractères ou bien elle retournera
«&nbsp;0&nbsp;» si la chaîne de caractères n'est pas trouvée. En utilisant la
variable «&nbsp;mystring&nbsp;», nous pouvons utiliser cette fonction de cette
façon&nbsp;:
</p>

<pre caption="Exemple de la fonction index()">
print index(mystring,"you")
</pre>

<p>
Awk affiche&nbsp;:
</p>

<pre caption="Résultat affiché">
9
</pre>

<p>
Nous allons passer à deux fonctions plus faciles&nbsp;:
«&nbsp;tolower()&nbsp;» et «&nbsp;toupper()&nbsp;». Comme vous pouvez le
deviner, ces fonctions retournent la chaîne de caractères avec tous les
caractères convertis respectivement en minuscules ou en majuscules.  Notez que
«&nbsp;tolower()&nbsp;» et «&nbsp;toupper()&nbsp;» retournent la nouvelle
chaîne de caractères et ne modifient pas celle d'origine. Ce code&nbsp;:
</p>

<pre caption="Convertir des chaînes en minuscules ou en majuscules">
print tolower(mystring)
print toupper(mystring)
print mystring
</pre>

<p>
Ce code affiche le résultat suivant&nbsp;:
</p>

<pre caption="Résultat affiché">
how are you doing today?
HOW ARE YOU DOING TODAY?
How are you doing today?
</pre>

<p>
C'est très bien, mais comment pouvons-nous extraire exactement une sous-chaîne
de caractères ou même un simple caractère d'une chaîne de caractères&nbsp;?
C'est là que «&nbsp;substr()&nbsp;» intervient. Voici comment utiliser
«&nbsp;substr()&nbsp;»&nbsp;:
</p>

<pre caption="Exemple de la fonction substr()">
mysub=substr(mystring,startpos,maxlen)
</pre>

<p>
«&nbsp;mystring&nbsp;» doit être soit une variable de type chaîne de caractères
ou une chaîne de caractères à partir de laquelle vous souhaitez extraire une
sous-chaîne de caractères. «&nbsp;startpos&nbsp;» correspond à la position du
caractère de départ et «&nbsp;maxlen&nbsp;» à la longueur maximale de la chaîne
de caractères que vous souhaitez extraire. Notez que j'ai dit longueur
maximale&nbsp;: si «&nbsp;length(mystring)&nbsp;» est plus petit que
«&nbsp;startpos + maxlen&nbsp;», votre résultat sera tronqué.
«&nbsp;substr()&nbsp;» ne modifie pas la chaîne de caractères d'origine mais
retourne la sous-chaîne de caractères à la place. Voici un exemple&nbsp;:
</p>

<pre caption="Un autre exemple">
print substr(mystring,9,3)
</pre>

<p>
Awk va afficher&nbsp;:
</p>

<pre caption="Ce qu'Awk va afficher">
you
</pre>

<p>
Si vous avec l'habitude de programmer dans un langage qui utilise des index de
tableau pour accéder à des parties d'une chaîne de caractères (ce qu'Awk ne
fait pas), mettez vous dans la tête que «&nbsp;substr()&nbsp;» s'y substitue en
Awk. Vous aurez besoin de l'utiliser pour extraire de simples caractères et des
sous-chaînes de caractères parce qu'Awk est un langage basé sur des chaînes de
caractères, vous utiliserez donc souvent cette fonction.
</p>

<p>
Maintenant, nous allons passer à des fonctions plus puissantes, la première
d'entre elles est «&nbsp;match()&nbsp;». «&nbsp;match()&nbsp;» ressemble
beaucoup à «&nbsp;index()&nbsp;» à l'exception près qu'au lieu de rechercher
une sous-chaîne de caractères comme «&nbsp;index()&nbsp;», elle recherche une
expression régulière. La fonction «&nbsp;match()&nbsp;» retourne la position de
départ de la correspondance ou zéro s'il n'a pas trouvé de correspondance. De
plus, «&nbsp;match()&nbsp;» renseignera deux variables appelées RSTART et
RLENGTH. RSTART contient la valeur de retour (la position de la première
correspondance) et RLENGTH contient la longueur de la chaîne de caractères
trouvée (ou -1 si aucune correspondance n'a été trouvée). En utilisant RSTART,
RLENGTH, «&nbsp;substr()&nbsp;» et une petite boucle, vous pouvez facilement
itérer toutes les correspondances trouvées dans votre chaîne de caractères.
Voici un exemple de l'utilisation de la fonction «&nbsp;match()&nbsp;»&nbsp;:
</p>

<pre caption="Exemple d'utilisation de match()">
print match(mystring,/you/), RSTART, RLENGTH
</pre>

<p>
Awk affiche&nbsp;:
</p>

<pre caption="Résultat affiché par la fonction précédente">
9 9 3
</pre>

</body>
</section>
<section>
<title>Substitution d'une chaîne de caractères</title>
<body>

<p>
Maintenant, nous allons nous intéresser à un couple de fonctions de
substitution de chaînes de caractères&nbsp;: «&nbsp;sub&nbsp;» et
«&nbsp;gsub()&nbsp;». Celles-ci diffèrent légèrement des fonctions que nous
avons étudiées jusqu'à présent puisqu'elles modifient la chaîne de caractères
d'origine. Voici comment appeler la fonction «&nbsp;sub()&nbsp;»&nbsp;:
</p>

<pre caption="Modèle d'utilisation de la fonction sub()">
sub(regexp,replstring,mystring)
</pre>

<p>
Quand vous utilisez la fonction «&nbsp;sub&nbsp;», celle-ci trouve la première
séquence de caractères dans la chaîne de caractères «&nbsp;mystring&nbsp;» qui
correspond à l'expression régulière «&nbsp;regexp&nbsp;» et remplace cette
séquence avec la chaîne de caractères «&nbsp;replstring&nbsp;».
«&nbsp;sub()&nbsp;» et «&nbsp;gsub()&nbsp;» utilise les mêmes arguments. Leur
seule différence est que «&nbsp;sub&nbsp;» remplace la première expression
régulière correspondante (s'il y en a une) et «&nbsp;gsub()&nbsp;» réalise un
remplacement global, remplaçant ainsi toutes les correspondances rencontrées
dans la chaîne de caractères. Voici un exemple d'utilisation des fonctions
«&nbsp;sub()&nbsp;» et «&nbsp;gsub()&nbsp;»:
</p>

<pre caption="Exemple d'utilisation des fonctions sub() et gsub()">
sub(/o/,"O",mystring)
print mystring
mystring="How are you doing today?"
gsub(/o/,"O",mystring)
print mystring
</pre>

<p>
Nous avons dû réaffecter la variable «&nbsp;mystring&nbsp;» à sa valeur
initiale car le premier appel de la fonction «&nbsp;sub()&nbsp;» a modifié
directement la variable «&nbsp;mystring&nbsp;». Une fois exécuté, ce code
affiche le résultat suivant&nbsp;:
</p>

<pre caption="Résultat affiché">
HOw are you doing today?
HOw are yOu dOing tOday?
</pre>

<p>
Bien sûr, des expressions régulières plus complexes sont possibles. Je vous
laisse tester des expressions régulières plus compliquées.
</p>

<p>
Nous terminerons cette découverte de fonctions de chaînes de caractères en vous
présentant une fonction appelée «&nbsp;split()&nbsp;». Le rôle de
«&nbsp;split()&nbsp;» est de «&nbsp;découper&nbsp;» une chaîne de caractères et
d'en placer les différentes parties dans un tableau indexé par des nombres
entiers. Voici un exemple de l'utilisation de la fonction
«&nbsp;split()&nbsp;»&nbsp;:
</p>

<pre caption="Exemple d'utilisation de la fonction split()">
numelements=split("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",mymonths,",")
</pre>

<p>
Lors de l'appel de la fonction «&nbsp;split()&nbsp;», le premier argument
contient directement la chaîne de caractères ou la variable à
«&nbsp;découper&nbsp;». Pour le deuxième argument, vous devez spécifier le nom
du tableau dans lequel «&nbsp;split()&nbsp;» stockera les différentes parties
de la chaîne de caractères découpée. Pour le troisième argument, vous spécifiez
le séparateur qui sera utiliser pour «&nbsp;découper&nbsp;» les chaînes de
caractères. Une fois exécuté, «&nbsp;split()&nbsp;» retourne le nombre de
chaînes de caractères issu du «&nbsp;découpage&nbsp;». «&nbsp;split()&nbsp;»
affecte chacune de ces chaînes de caractères à un tableau d'index commençant à
«&nbsp;1&nbsp;», donc le code suivant&nbsp;:
</p>

<pre caption="Exemple de code">
print mymonths[1],mymonths[numelements]
</pre>

<p>
... affichera&nbsp;:
</p>

<pre caption="Exemple d'affichage">
Jan Dec
</pre>

</body>
</section>
<section>
<title>Particularité de certaines fonctions</title>
<body>

<p>
N.B.&nbsp;: quand vous utilisez la fonction «&nbsp;length()&nbsp;»,
«&nbsp;sub()&nbsp;» ou «&nbsp;gsub()&nbsp;», vous pouvez omettre le dernier
argument&nbsp;; Awk appliquera alors l'appel de la fonction à «&nbsp;$0&nbsp;»
(la ligne courante entière). Pour afficher la longueur de chaque ligne d'un
fichier, utilisez ce script Awk&nbsp;:
</p>

<pre caption="Le code affichant la longueur de chaque ligne d'un fichier">
{
    print length()
}
</pre>

</body>
</section>
<section>
<title>Amusement financier</title>
<body>

<p>
Il y a quelques semaines, j'ai décidé d'écrire mon propre programme de tenue de
compte en Awk. Je voulais un fichier texte délimité par des tabulations dans
lequel je pouvais saisir mes derniers dépôts et retraits d'argent. L'idée était
de traiter ces données par un script Awk qui additionnerait automatiquement
tous les montants et m'en donnerait la balance. Voici comment j'ai enregistré
toutes mes transactions dans mon «&nbsp;livre de tenue de comptes
ASCII&nbsp;»&nbsp;:
</p>

<pre caption="Livre de tenue de comptes ASCII pour enregistrer les transactions">

23 Aug 2000    food    -    -    Y    Jimmy's Buffet    30.25
</pre>

<p>
Chaque champ dans ce fichier est séparé par une ou plusieurs tabulations. Après
la date (champ 1, $1), il y a deux champs appelés «&nbsp;rubrique de
dépense&nbsp;» et «&nbsp;rubrique de revenu&nbsp;». Quand je saisis une dépense
comme sur la ligne ci-dessus, je mets un nom de quatre lettres dans le champs
de la rubrique de dépense et un «&nbsp;-&nbsp;» (entrée vierge) dans le champ
de rubrique de revenu. Cela signifie que cet enregistrement correspond à une
«&nbsp;dépense de nourriture&nbsp;» :) Voici à quoi un dépôt
ressemblerait&nbsp;:
</p>

<pre caption="Exemple d'une saisie d'un dépôt">

23 Aug 2000    -    inco    -    Y    Boss Man        2001.00
</pre>

<p>
Dans ce cas, je mets un «&nbsp;-&nbsp;» dans la rubrique de dépense et
«&nbsp;inco&nbsp;» dans la rubrique de revenu. «&nbsp;inco&nbsp;» est un nom
pour les revenus génériques (virement de paye par exemple). En utilisant des
noms de rubriques, cela me permet de produire un bilan de mes revenus et de mes
dépenses par rubrique. Tous les autres champs sont assez explicites. Le champ
«&nbsp;"Y" ou "N"&nbsp;» indique si la transaction a été enregistrée sur mon
compte. Ensuite, les derniers champs sont la description de la transaction et
le montant (positif) de la transaction.
</p>

<p>
L'algorithme utilisé pour calculer la balance n'est pas trop difficile. Awk a
simplement besoin de lire chaque ligne, une par une. Si une dépense est
renseignée et qu'il n'y a pas de revenu (c'est à dire «&nbsp;-&nbsp;») alors le
montant est un débit. Si un revenu est renseigné et qu'il n'y a pas de dépense
(c'est à dire «&nbsp;-&nbsp;», alors le montant est une recette. Et si les deux
(dépense et revenu) sont renseignés, alors ce montant est un
«&nbsp;transfert&nbsp;»&nbsp;:&nbsp;c'est à dire que le montant sera soustrait
de la dépense et ajouté au revenu. De plus, toutes ces rubriques sont
virtuelles mais sont très utiles pour suivre les revenus et les dépenses et
pour suivre son budget.
</p>

</body>
</section>
<section>
<title>Le code</title>
<body>

<p>
L'heure est venue de nous intéresser au code. Nous commençons par la première
ligne, le bloc BEGIN et une définition de fonction&nbsp;:
</p>

<pre caption="La balance, 1ère partie">
#!/usr/bin/env awk -f
BEGIN {
    FS="\t+"
    months="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
}

function monthdigit(mymonth) {
    return (index(months,mymonth)+3)/4
}
</pre>

<p>
En ajoutant la première ligne «&nbsp;#!...&nbsp;» à n'importe quel script Awk,
cela lui permet d'être directement exécuté à partir du shell, à condition que
vous réalisiez au préalable un <c>chmod +x monscript</c>. Les lignes restantes
définissent notre bloc BEGIN, qui sera exécuté avant qu'Awk commence à traiter
le fichier de notre livre de tenue de comptes. Nous affectons FS «&nbsp;Field
Separator&nbsp;», le séparateur de champs à «&nbsp;\t+&nbsp;», qui indique à
Awk que les champs sont séparés par une ou plusieurs tabulations. En plus, nous
définissons une chaîne de caractères appelée months (mois) qui est utilisée par
notre fonction «&nbsp;monthdigit()&nbsp;» que l'on retrouve ensuite.
</p>

<p>
Les trois dernières lignes vous montrent comment définir votre propre fonction
en Awk. Le format est simple&nbsp;:&nbsp;Tapez «&nbsp;function&nbsp;» puis le
nom de la fonction, puis les paramètres séparés par des virgules à l'intérieur
de parenthèses. Après ça, un bloc de code «&nbsp;{&nbsp;}&nbsp;contient le code
que votre fonction doit exécuter. Toutes les fonctions peuvent accéder à des
variables globales (comme notre variable «&nbsp;months&nbsp;»). De plus, Awk
fournit une directive «&nbsp;return&nbsp;» qui permet à la fonction de
retourner une valeur et fonctionne de la même façon que la directive
«&nbsp;return&nbsp;» que l'on retrouve en C, Python et autres langages. Cette
fonction convertit un nom de mois dans un format de chaîne de caractères
composée de 3 lettres en son équivalent numérique. Par exemple&nbsp;:
</p>

<pre caption="Exemple d'utilisation de la fonction monthdigit()">
print monthdigit("Mar")
</pre>

<p>
... Affichera&nbsp;:
</p>

<pre caption="Exemple d'affichage résultant de la fonction monthdigit()">
3
</pre>

<p>
Maintenant, passons à d'autres fonctions supplémentaires.
</p>

</body>
</section>
<section>
<title>Fonctions financières</title>
<body>

<p>
Voici encore trois fonctions supplémentaires qui vont nous réaliser des
opérations comptables. Notre bloc de code principal, que nous verrons bientôt,
traite séquentiellement chaque ligne du fichier du livre de tenue de comptes,
appelant une de ces fonctions, stockant alors les transactions appropriées dans
un tableau Awk. Il y a trois types de transactions&nbsp;:&nbsp; un revenu
(doincome), un débit (doexpense) et un transfert (dotransfer). Vous remarquerez
que ces trois fonctions admettent un argument, appelé «&nbsp;mybalance&nbsp;».
«&nbsp;mybalance&nbsp;» correspond à un tableau à deux dimensions, que nous
utiliserons comme argument. Jusqu'ici, nous n'avons pas vu les tableaux à deux
dimensions. Cependant, comme vous pouvez le voir ci-dessous, la syntaxe est
tout à fait simple&nbsp;:&nbsp;Séparez juste chaque dimension avec une virgule
et c'est parti !
</p>

<p>
Nous enregistrons des informations dans «&nbsp;mybalance&nbsp;» comme
suit&nbsp;: la première dimension du tableau varie de 0 à 12 et spécifie le
mois ou zéro pour l'année entière. Notre seconde dimension est une rubrique de
quatre lettres, comme «&nbsp;food&nbsp;» ou
«&nbsp;inco&nbsp;»&nbsp;:&nbsp;c'est la rubrique réelle dont nous nous
occupons. Donc, pour trouver la balance de l'année entière pour la rubrique
«&nbsp;food&nbsp;», vous l'aurez avec «&nbsp;mybalance[0,"food"]&nbsp;». Pour
trouver les revenus de Juin, vous l'aurez avec «&nbsp;mybalance[6,"inco"].
</p>

<pre caption="Trouver des informations relatives aux revenus">

function doincome(mybalance) {
    mybalance[curmonth,$3] += amount
    mybalance[0,$3] += amount
}

function doexpense(mybalance) {
    mybalance[curmonth,$2] -= amount
    mybalance[0,$2] -= amount
}

function dotransfer(mybalance) {
    mybalance[0,$2] -= amount
    mybalance[curmonth,$2] -= amount
    mybalance[0,$3] += amount
    mybalance[curmonth,$3] += amount
}
</pre>

<p>
Quand «&nbsp;doincome()&nbsp;» ou n'importe quelle autre fonction est appelée,
nous enregistrons la transaction à deux endroits&nbsp;:
«&nbsp;mybalance[0,category]&nbsp;» et
«&nbsp;mybalance[curmonth,category]&nbsp;» respectivement la balance de la
rubrique pour l'année entière et la balance de la rubrique pour le mois en
cours. Cela nous permet de générer ainsi facilement soit le bilan annuel ou
mensuel des revenus/dépenses.
</p>

<p>
Si vous regardez ces fonctions, vous remarquerez que le tableau référencé par
«&nbsp;mybalance&nbsp;» leur est passé en argument. De plus, nous faisons
allusions à plusieurs variables globales&nbsp;: «&nbsp;curmonth&nbsp;» qui
stocke la valeur numérique de l'enregistrement en cours, «&nbsp;$2&nbsp;» (la
rubrique de dépense), «&nbsp;$3&nbsp;» (la rubrique de revenu) et le montant
«&nbsp;$7&nbsp;». Quand les fonctions «&nbsp;doincome()&nbsp;» et les autres du
même type sont appelées, toutes ces variables sont déjà renseignées
correctement pour l'enregistrement (ligne) en cours de traitement.
</p>

</body>
</section>
<section>
<title>Le bloc principal</title>
<body>

<p>
Voici le bloc de code principal qui contient le code qui va traiter chaque
ligne de données en entrée. Souvenez-vous, parce que nous avons renseigné la
variable FS correctement, nous pouvons appeler le premier champ comme $1, le
second champ comme $2, etc... Quand les fonctions «&nbsp;doincome()&nbsp;» et
autres fonctions du même type sont appelées, les fonctions peuvent accéder aux
valeurs de «&nbsp;curmonth&nbsp;», $2, $3 et le montant de l'intérieur de la
fonction. Regardez ce code et voyons enseuite pour une explication.
</p>

<pre caption="La balance, 3ème partie">

{
    curmonth=monthdigit(substr($1,4,3))
    amount=$7

    # Enregistre toutes les rubriques rencontrées
    if ( $2 != "-" )
        globcat[$2]="yes"
    if ( $3 != "-" )
        globcat[$3]="yes"

    # Comptabilise correctement la transaction
    if ( $2 == "-" ) {
        if ( $3 == "-" ) {
            print "Erreur: Ni inc, ni exp n'ont été renseignés !"
            exit 1
        } else {
            # C'est un revenu
            doincome(balance)
            if ( $5 == "Y" )
                doincome(balance2)
        }
    } else if ( $3 == "-" ) {
        # C'est une dépense
        doexpense(balance)
        if ( $5 == "Y" )
            doexpense(balance2)
    } else {
        # C'est un transfert
        dotransfer(balance)
        if ( $5 == "Y" )
            dotransfer(balance2)
    }
}
</pre>

<p>
Dans le bloc principal, les deux premières lignes renseignent la variable
«&nbsp;curmonth&nbsp;» avec un entier compris entre 1 et 12 et renseigne le
montant au 7<sup>ème</sup> champ (pour rendre le code plus facile à
comprendre).  Ensuite, nous avons quatre lignes intéressantes où nous écrivons
les valeurs dans un tableau appelé «&nbsp;globcat&nbsp;».
«&nbsp;globcat&nbsp;», le tableau des rubriques globales, est utilisé pour
enregistrer toutes les rubriques rencontrées dans le fichier&nbsp;:
«&nbsp;inco&nbsp;», «&nbsp;misc&nbsp;», «&nbsp;food&nbsp;», «&nbsp;util&nbsp;»,
etc... Par exemple, si «&nbsp;$2 == "inco"&nbsp;», nous renseignons
«&nbsp;globcat["inco"]&nbsp;» à «&nbsp;yes&nbsp;». Plus tard, nous pouvons
itérer notre liste de rubriques avec une simple boucle «&nbsp;for (x in
globcat)&nbsp;».
</p>

<p>
Sur les vingt lignes suivantes environ, nous analysons les champs $2 et $3 et
enregistrons la transaction appropriée. Si «&nbsp;$2 == "-"&nbsp;» et «&nbsp;$3
!="-"&nbsp;», nous sommes en présence d'un revenu donc nous appelons la
fonction «&nbsp;doincome()&nbsp;». Si la situation est inverse, nous appelons
la fonction «&nbsp;doexpense()&nbsp;». Et si $2 et $3 contiennent tous les deux
une rubrique, nous appelons la fonction «&nbsp;dotranfer()&nbsp;». Chaque fois,
nous passons le tableau «&nbsp;balance&nbsp;» comme argument à ces fonctions
pour que les données appropriées puissent y être enregistrées.
</p>

<p>
Vous remarquerez aussi plusieurs lignes qui disent que «&nbsp;si
(&nbsp;$5&nbsp;==&nbsp;"Y"&nbsp;)&nbsp;», la même transaction doit alors être
enregistrée dans «&nbsp;balance2&nbsp;». Que faisons-nous exactement ici&nbsp;?
Vous vous rappelez que $5 contient soit un "Y" ou un "N" indiquant si la
transaction a été réalisée dans le compte. Parce que nous enregistrons la
transaction dans «&nbsp;balance2&nbsp;» seulement si la transaction a été
enregistrée, «&nbsp;balance2&nbsp;» contient la balance actuelle du compte
tandis que «&nbsp;balance&nbsp;» contient toutes les transactions, qu'elles
aient été enregistrées ou non sur le compte. Vous pouvez utiliser
«&nbsp;balance2&nbsp;» pour vérifier votre entrée de données (il devrait
correspondre à la balance de votre compte courant de votre banque et vous
pouvez utiliser «&nbsp;balance&nbsp;» pour être sûr que vous n'êtes pas à
découvert sur votre compte, étant donné qu'il tient compte par exemple des
chèques qui n'ont pas encore été encaissés.
</p>

</body>
</section>
<section>
<title>Générer le rapport</title>
<body>

<p>
Après que le bloc principal ait répété le même processus pour chaque
enregistrement en entrée, nous avons maintenant un enregistrement assez complet
d'opérations au crédit et au débit du compte décomposées par rubrique et par
mois. Maintenant, tout ce dont nous avons besoin de faire est de définir un
bloc END qui va générer un report, en voici un modeste dans notre cas&nbsp;:
</p>

<pre caption="Générer le rapport final">
END {
    bal=0
    bal2=0
    for (x in globcat) {
        bal=bal+balance[0,x]
        bal2=bal2+balance2[0,x]
    }
    printf("Vos fonds disponibles : %10.2f\n", bal)
    printf("La balance de votre compte : %10.2f\n", bal2)
}
</pre>

<p>
Ce report affiche un résumé qui ressemble à quelque chose de ce genre&nbsp;:
</p>

<pre caption="Rapport final">
Vos fonds disponibles :    1174.22
La balance de votre compte :    2399.33
</pre>

<p>
Dans notre bloc END, nous utilisons la construction «&nbsp;for (x in
globcat)&nbsp;» pour itérer à travers chaque rubrique, pour comptabiliser la
balance principale basée sur toutes les transactions enregistrées. Nous
comptabilisons en fait deux balances, l'une pour les fonds disponibles et une
autre pour la balance du compte. Pour exécuter le programme et traiter vos
données financières que vous avez saisies dans un fichier appelé
<path>mycheckbook.txt</path>, mettez tout le code vu précédemment dans un
fichier texte appelé <path>balance</path> et faîtes un <c>chmod +x balance</c>
puis tapez <c>./balance mycheckbook.txt</c>. Le script balance ajoutera alors
toutes vos transactions et affichera pour vous un résumé de votre balance de
deux lignes.
</p>

</body>
</section>
<section>
<title>Possibilités d'évolution du programme</title>
<body>

<p>
J'utilise une version plus avancée de ce programme pour gérer mes finances
personnelles et professionnelles. Ma version (que je ne peux pas inclure ici
par manque de place) affiche un bilan mensuel de mes revenus et de mes
dépenses, incluant les totaux annuels, le revenu net et d'autres petites
informations utiles. Encore mieux, il génère les données dans un format HTML,
ce qui me permets de les consulter dans un navigateur Internet :) Si vous
trouvez ce programme utile, je vous encourage à ajouter ces fonctionnalités.
Vous n'aurez pas besoin d'enregistrer des informations supplémentaires. Toutes
les informations dont vous avez besoin sont déjà dans «&nbsp;balance&nbsp;» et
«&nbsp;balance2&nbsp;». Vous n'avez juste qu'à mettre à jour le bloc END et
vous serez prêt pour les affaires&nbsp;!
</p>

<p>
J'espère que vous avez apprécié cette série d'articles. Pour plus
d'informations sur Awk, consultez les ressources listées ci-dessous.
</p>

</body>
</section>
</chapter>

<chapter>
<title>Ressources</title>
<section>
<body>

<ul>
  <li>
    Consultez les autres articles de Daniel sur Awk&nbsp;&nbsp;Awk par
    l'exemple, <uri link="l-awk1.xml">1ère partie</uri> et <uri
    link="l-awk2.xml">2ème partie</uri>.
  </li>
  <li>
    Si vous recherchez un bon vieux livre, <uri
    link="http://www.oreilly.com/catalog/sed2/">Sed &amp; Awk, 2nd
    Edition</uri> d'Oreilly est un très bon choix.
  </li>
  <li>
    Consultez aussi la <uri
    link="http://www.faqs.org/faqs/computer-lang/awk/faq/">FAQ comp.lang.awk
    </uri>. Elle contient beaucoup de liens supplémentaires sur Awk.
  </li>
  <li>
    <uri link="http://sparky.rice.edu/~hartigan/awk.html">Awk tutorial</uri> de
    Patrick Hartigani est présenté avec des scripts Awk avancés.
  </li>
  <li>
    <uri link="http://www.tasoft.com/tawk.html">Thompson's TAWK Compiler</uri>
    compile les scripts Awk en exécutables binaires rapides. Des versions sont
    disponibles pour Windows, OS/2, DOS et UNIX.
  </li>
  <li>
    <uri link="http://www.gnu.org/software/gawk/manual/gawk.html">The GNU Awk
    User's Guide</uri> est disponible comme référence en ligne.
  </li>
</ul>

</body>
</section>
</chapter>
</guide>






^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2008-11-14 13:07 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-11-14 13:07 [gentoo-commits] gentoo commit in xml/htdocs/doc/fr/articles: l-awk3.xml Marion Age (titefleur)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox