<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://lea-linux.org/docs/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=BernardTV</id>
	<title>Lea Linux - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://lea-linux.org/docs/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=BernardTV"/>
	<link rel="alternate" type="text/html" href="https://lea-linux.org/documentations/Sp%C3%A9cial:Contributions/BernardTV"/>
	<updated>2026-04-18T08:24:16Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.40.1</generator>
	<entry>
		<id>https://lea-linux.org/docs/index.php?title=GAWK&amp;diff=11186</id>
		<title>GAWK</title>
		<link rel="alternate" type="text/html" href="https://lea-linux.org/docs/index.php?title=GAWK&amp;diff=11186"/>
		<updated>2005-12-21T13:34:26Z</updated>

		<summary type="html">&lt;p&gt;BernardTV : /* Les enregistrements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Développer sous Linux]]&lt;br /&gt;
= Introduction à (g)awk =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;leatitre&amp;quot;&amp;gt;Introduction à (g)awk&amp;lt;/div&amp;gt;&amp;lt;div class=&amp;quot;leapar&amp;quot;&amp;gt;par [mailto:xgarreau@club-internet.fr Xavier GARREAU]&amp;lt;/div&amp;gt;&amp;lt;div class=&amp;quot;leadesc&amp;quot;&amp;gt;Cet article va vous permettre de vous familiariser avec (g)awk, langage de programmation permettant de faire très rapidement des traitements intéressants sur des données diverses. Après la présentation générale, on réalisera deux filtres inspirés de filtres ayant été réellement développés.&amp;lt;/div&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
=== Présentation ===&lt;br /&gt;
&lt;br /&gt;
Vous vous demandez surement pourquoi ce (g) avant awk, non ? Ce n&#039;est pas le g de gnome, ni celui de gtk+ mais celui de gnu. Extrait de la page de manuel (&amp;lt;code&amp;gt;man gawk&amp;lt;/code&amp;gt; ou &amp;lt;code&amp;gt;man awk&amp;lt;/code&amp;gt;) :&amp;lt;br /&amp;gt;&#039;&#039;&amp;quot;Gawk est l&#039;implémentation du projet GNU du langage de programmation AWK, lequel se conforme à la définition du langage dans la norme &#039;&#039;&#039;POSIX1003.2 Command Language and Utilities Standard&#039;&#039;&#039;. Cette version est basée, elle, sur la description d&#039;AWK de Aho, Kernighan and Weinberger, plus les spécificités supplémentaires se trouvant dans la version de awk de l&#039;UNIX System V version 4. Gawk ajoute également des extensions plus récentes des Laboratoires Bell ainsi que des extensions spécifiques à GNU.&amp;quot;&#039;&#039;&amp;lt;br /&amp;gt; Je ne mets pas ce pavé pour remplir de l&#039;espace mais pour que les personnes à la base de choses que je ne fais que présenter soient reconnues pour leur travail et que l&#039;on sache de quoi on parle.&lt;br /&gt;
&lt;br /&gt;
Nous allons pouvoir commencer:&lt;br /&gt;
&lt;br /&gt;
=== Qu&#039;est ce que c&#039;est ===&lt;br /&gt;
&lt;br /&gt;
awk (j&#039;utiliserai awk par la suite, mais c&#039;est de gawk que l&#039;on parle) est un langage interprété, installé par défaut sur les distributions linux (au moins rh et mandrake) dans le répertoire /bin. Il permet de traiter des fichiers de données structurées.&amp;lt;br /&amp;gt; Un programme awk est une suite de blocs de code compris entre {} (c&#039;est pas très original) qui sont appliqués aux lignes (par défaut) de données du fichier si un &amp;quot;modèle&amp;quot; est vérifié. La page de manuel nous donne les différents types de modèles utilisables : &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
| &amp;lt;code&amp;gt; BEGIN &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté au début du programme, &#039;&#039;&#039;une seule fois&#039;&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; END &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté à la fin du programme, &#039;&#039;&#039;une seule fois&#039;&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; /expression régulière/ &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté si les données en cours de traitement correspondent à l&#039;expression régulière. Si vous ne connaissez pas les expressions régulières, lisez la page &amp;lt;code&amp;gt;man egrep&amp;lt;/code&amp;gt;.&amp;lt;br /&amp;gt;&#039;&#039;&#039;Un exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;/^#/&amp;lt;/code&amp;gt; Permet de selectionner les lignes commençant par un #.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; expression relationnelle &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté si l&#039;expression est vraie.&amp;lt;br /&amp;gt;&#039;&#039;&#039;Un exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;maVariable==5&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; modèle &amp;amp;&amp;amp; modèle &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté si les deux modèles sont vérifiés.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; modèle || modèle &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté si au moins un des modèles est vérifié.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; modèle0 ? modèle1 : modèle2 &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté si les modèles 0 et 1 sont vérifiés ou si le modèle2 uniquement est vérifié.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; (modèle) &amp;lt;/code&amp;gt;&lt;br /&gt;
| Permet de grouper les modèles.&amp;lt;br /&amp;gt; Un exemple : &amp;lt;code&amp;gt;(modèle0 || modèle1) &amp;amp;&amp;amp; modèle2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; ! modèle &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté si le modèle n&#039;est pas vérifié.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; modèle1, modèle2 &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté pour la partie des données en cours commençant par modèle1 et finissant par modèle2.&amp;lt;br /&amp;gt;&#039;&#039;&#039;Un exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;/\/\*/, /\*\//&amp;lt;/code&amp;gt; pour afficher les commentaires multilignes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Premiers pas ==&lt;br /&gt;
&lt;br /&gt;
=== Les enregistrements ===&lt;br /&gt;
&lt;br /&gt;
Pour awk, les blocs de données lues sont séparés par un caractère contenu dans la variable &#039;&#039;&#039;RS&#039;&#039;&#039; (Record Separator, retour à la ligne par défaut). On peut accéder à l&#039;intégralité du bloc grâce à la variable &#039;&#039;&#039;$0&#039;&#039;&#039;. C&#039;est ce qu&#039;on appelle un enregistrement.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Un exemple&#039;&#039;&#039; : Tapez &amp;lt;code&amp;gt;awk &#039;{ print $0 }&#039; un_fichier&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt; Passionnant, non ? vous venez de réinventer la commande &amp;lt;code&amp;gt;cat&amp;lt;/code&amp;gt; ;-) ! &amp;lt;br /&amp;gt;&#039;&#039;&#039;Un autre exemple&#039;&#039;&#039; : Tapez &amp;lt;code&amp;gt;awk &#039;/\/\*/, /\*\// { print $0 }&#039; un_fichier_c_avec_des_commentaires&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt; C&#039;est déjà plus sympa, hein ? &amp;lt;br /&amp;gt;&#039;&#039;&#039;Un dernier exemple&#039;&#039;&#039; : Tapez &amp;lt;code&amp;gt;awk &#039;! (/^ *#/ || /^$/) { print $0 }&#039; un_fichier_conf&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt; Vous n&#039;aviez jamais vu votre fichier de config d&#039;Apache comme ça, si ?&lt;br /&gt;
&lt;br /&gt;
=== Les champs ===&lt;br /&gt;
&lt;br /&gt;
Ah, la nature ... Courir nus dans les champs en se tenant la main ... &#039;&#039;&#039;NON&#039;&#039;&#039;, je vous arrête tout de suite.&amp;lt;br /&amp;gt; Chaque enregistrement est séparé en champs par un caractère contenu dans la variable FS (Field Separator, un espace par défaut). Les champs sont accessibles par les variables $1, $2, $3, etc ...&amp;lt;br /&amp;gt;Pour afficher le 3&amp;lt;sup&amp;gt;ème&amp;lt;/sup&amp;gt; champ de toutes les lignes de vos données à traiter, vous utilisez &amp;lt;code&amp;gt;print $3&amp;lt;/code&amp;gt;.&amp;lt;br /&amp;gt;&#039;&#039;&#039;Un exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;awk -F &#039;:&#039; &#039;{ print $1 &amp;quot; est &amp;quot; $5 }&#039; /etc/passwd&amp;lt;/code&amp;gt; pour afficher la description des utilisateurs de votre machine.&lt;br /&gt;
&lt;br /&gt;
=== Les variables ===&lt;br /&gt;
&lt;br /&gt;
Il existe bon nombre de variables prédéfinies en awk. Je vais vous en donner la liste résumée, encore une fois, je n&#039;invente rien et je ne créée rien, je ne fais que vous refaire une lecture de la page de manuel. D&#039;ailleurs pour avoir une liste exhaustive des variables, consultez la.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
| ARGC&lt;br /&gt;
| Si vous avez fait du c, vous vous en doutez ! Sinon, je vous le dis. Cette variable contient le nombre d&#039;arguments passés &#039;&#039;&#039;au programme. (sans les options passées à awk)&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| ARGV&lt;br /&gt;
| Un tableau contenant les &#039;&#039;ARGC&#039;&#039; paramètres, indéxé de 0 à ARGC-1. Ce sont tous les fichiers à traiter&lt;br /&gt;
|-&lt;br /&gt;
| CONVFMT&lt;br /&gt;
| Le format par défaut pour l&#039;affichage des nombres, &amp;quot;%.6g&amp;quot; par défaut&lt;br /&gt;
|-&lt;br /&gt;
| ENVIRON&lt;br /&gt;
| Un tableau contenant les variables d&#039;environnement. &#039;&#039;&#039;Exemple&#039;&#039;&#039; &amp;lt;code&amp;gt;ENVIRON[&amp;quot;PATH&amp;quot;]&amp;lt;/code&amp;gt; contient votre path.&lt;br /&gt;
|-&lt;br /&gt;
| FIELDWIDTHS&lt;br /&gt;
| Pour le cas de traitement de données non délimités mais contenant des champs de largeur fixe.&amp;lt;br /&amp;gt; Cette variable est de la forme &amp;lt;code&amp;gt;largeur_champ_1 largeur_champ_2 largeur_champ_3 etc...&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| FNR&lt;br /&gt;
| Le numéro de l&#039;enregistrement actuellement en cours de traitement.&amp;lt;br /&amp;gt;&#039;&#039;&#039;Un exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;awk &#039;{print FNR &amp;quot;: &amp;quot; $0}&#039; un_fichier&amp;lt;/code&amp;gt; permet d&#039;afficher le fichier avec les numéros de lignes.&amp;lt;br /&amp;gt;&#039;&#039;&#039;Un autre exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;awk &#039;{print FNR &amp;quot;: &amp;quot; $0}&#039; un_fichier | grep ^45:&amp;lt;/code&amp;gt; permet d&#039;afficher la ligne 45 du fichier &#039;&#039;un_fichier&#039;&#039;. On fait appel à grep, ce n&#039;est plus du 100% awk mais c&#039;est beau la diversité, non ?&lt;br /&gt;
|-&lt;br /&gt;
| FS&lt;br /&gt;
| Le séparateur de champs. No comment !&lt;br /&gt;
|-&lt;br /&gt;
| IGNORECASE&lt;br /&gt;
| En gros, permet de ne pas prendre en compte la casse lors des comparaisons de chaines de caractères entre elles où avec des expressions régulières. Voir la page de manuel pour les détails.&lt;br /&gt;
|-&lt;br /&gt;
| NF&lt;br /&gt;
| Norme Française ... NON, Number of fields : C&#039;est le nombre de champs de l&#039;enregistrement en cours.&lt;br /&gt;
|-&lt;br /&gt;
| NR&lt;br /&gt;
| Number of Records : Le nombre d&#039;enregistrements traités jusqu&#039;à maintenant.&lt;br /&gt;
|-&lt;br /&gt;
| RS&lt;br /&gt;
| Le séparateur d&#039;enregistrements. No comment !&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bien entendu, vous pouvez également définir les vôtres.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Exemples :&#039;&#039;&#039;&lt;br /&gt;
: &amp;lt;code&amp;gt;maVar=3&amp;lt;/code&amp;gt; déclare et initialise la variable myVar à la valeur 3.&amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;print maVar&amp;lt;/code&amp;gt; affiche le &#039;&#039;&#039;contenu de la variable maVar&#039;&#039;&#039;.&amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;print $maVar&amp;lt;/code&amp;gt; affiche le &#039;&#039;&#039;champ n°maVar&#039;&#039;&#039; de l&#039;enregistrement en cours (ici, &#039;&#039;&#039;équivaut à print $3&#039;&#039;&#039;).&amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;print $(maVar-1)&amp;lt;/code&amp;gt; affiche le &#039;&#039;&#039;champ n°(maVar-1)&#039;&#039;&#039; de l&#039;enregistrement en cours (ici, &#039;&#039;&#039;équivaut à print $2&#039;&#039;&#039;).&amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;split(&amp;quot;toto:tata:titi:tutu&amp;quot;, arr, &amp;quot;:&amp;quot;)&amp;lt;/code&amp;gt; initialise le tableau arr à (&amp;quot;toto&amp;quot;,&amp;quot;tata&amp;quot;,...). On accède ensuite aux valeurs par &amp;lt;code&amp;gt;arr[1], arr[2], ..., arr[4]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Les fonctions ===&lt;br /&gt;
&lt;br /&gt;
Il y en a de nombreuses : &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour l&#039;affichage formaté, de textes et de nombres. &amp;lt;code&amp;gt;&#039;&#039;&#039;print printf ...&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* pour les opérations habituelles sur les chaines de caractères, concaténation, substitution, remplacement, recherche ... &amp;lt;code&amp;gt;&#039;&#039;&#039;gensub substr tolower index split ...&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* pour les accés aux systèmes de fichiers et au système &amp;lt;code&amp;gt;&#039;&#039;&#039;fflush close nextline system&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* pour les fonctions mathématiques &amp;lt;code&amp;gt;&#039;&#039;&#039;rand sin exp log ...&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* pour la gestion du temps &amp;lt;code&amp;gt;&#039;&#039;&#039;systime strftime&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Les possibilités de formatage importantes à votre disposition sont définies dans la page de manuel de awk.&lt;br /&gt;
&lt;br /&gt;
Et vous pouvez également définir vos fonctions grâce à la syntaxe : &amp;lt;tt&amp;gt; function nom_de_fonction(param1, param2, var_locale_1, var_locale_2) {&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; ou &amp;lt;tt&amp;gt; func nom_de_fonction(param1, param2 var_locale_1, var_locale_2) {&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; La déclaration des variables locales est étrange. Celà vient du fait que awk n&#039;était pas prévu pour permettre la créaton de fonctions. Il a donc été décidé, de les ajouter à la liste des paramètres, mais séparées par des espaces supplémentaires. L&#039;appel de la fonction, lui, ne contient que les paramètres. &#039;&#039;&#039;Exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;nom_de_fonction(5,2)&amp;lt;/code&amp;gt;. Les variables locales sont initialisées à chaine vide ou zéro.&lt;br /&gt;
&lt;br /&gt;
=== Blocs ===&lt;br /&gt;
&lt;br /&gt;
Merci à Jean-Louis pour m&#039;avoir montré que je n&#039;insistais pas assez sur le fonctionnement des blocs. C&#039;est grâce à lui que cette partie existe&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Utilisation des blocs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Prenons un exemple :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;#!/usr/bin/awk -f&amp;lt;/nowiki&amp;gt;&amp;lt;br /&amp;gt; BEGIN {&amp;lt;br /&amp;gt; print &amp;quot;début du script&amp;quot;&amp;lt;br /&amp;gt; maVariable=5&amp;lt;br /&amp;gt; nbLignes=0&amp;lt;br /&amp;gt; nbCommentaires=0&amp;lt;br /&amp;gt; nbCommentaires2=0&amp;lt;br /&amp;gt; print &amp;quot;maVariable vaut &amp;quot; maVariable&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; ( /^#/ || /^$/ ) {&amp;lt;br /&amp;gt; nbCommentaires++&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; {&amp;lt;br /&amp;gt; nbLignes++&amp;lt;br /&amp;gt; printf &amp;quot;%04d:%s\n&amp;quot;,FNR,$0&amp;lt;br /&amp;gt; if ( $0 ~ /^#/ || $0 ~ /^$/ ) {&amp;lt;br /&amp;gt; nbCommentaires2++&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; END {&amp;lt;br /&amp;gt; print &amp;quot;fin du script maVariable vaut toujours &amp;quot; maVariable&amp;lt;br /&amp;gt; print &amp;quot;Le script a traité &amp;quot; FNR &amp;quot; lignes dont &amp;quot; nbCommentaires &amp;quot;(=&amp;quot; nbCommentaires2 &amp;quot;) lignes vides ou commençant par un #&amp;quot;&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Explications :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Le bloc BEGIN est exécuté &#039;&#039;&#039;une fois&#039;&#039;&#039; au début, &#039;&#039;&#039;avant le traitement des données&#039;&#039;&#039;. Il affiche &amp;quot;début du script&amp;quot;, initialise les variables et affiche le contenu de &amp;lt;code&amp;gt;maVariable&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Un bloc qui est exécuté pour chaque ligne commençant par un # ou vide, il incrémente la variable nbCommentaires.&lt;br /&gt;
* Un Bloc exécuté pour toutes les lignes, il incrémente la variable &amp;lt;code&amp;gt;nbLignes&amp;lt;/code&amp;gt;, affiche la ligne préfixée par son numéro. Le numéro est formaté pour occupper quattre caractères. Les lignes suivantes (à partir du &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;) montrent l&#039;équivalence entre le bloc du dessus et un test if dans le bloc principal. La variable nbCommentaires2 est incrémentée pour chaque ligne commençant par un dièse ou vide.&lt;br /&gt;
* Le bloc END est exécuté &#039;&#039;&#039;une fois&#039;&#039;&#039; à la fin, &#039;&#039;&#039;après le traitement des données&#039;&#039;&#039;. On voit que la variable &amp;lt;code&amp;gt;maVariable&amp;lt;/code&amp;gt; est toujours définie et que son contenu n&#039;a pas été altéré. Il indique également le nombre total de lignes traitées et le nombre de lignes de commentaires ou vides présentes dans le fichier.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exécution&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;# chmod a+x ceScript.awk&amp;lt;/nowiki&amp;gt;&amp;lt;br /&amp;gt; # ./ceScript.awk unfichier.shell&amp;lt;br /&amp;gt; début du script&amp;lt;br /&amp;gt; maVariable vaut 5&amp;lt;br /&amp;gt; 0001:# Ce script affiche hello world&amp;lt;br /&amp;gt; 0002:&amp;lt;br /&amp;gt; 0003:echo &amp;quot;hello world&amp;quot;&amp;lt;br /&amp;gt; 0004:exit 0&amp;lt;br /&amp;gt; fin du script maVariable vaut toujours 5&amp;lt;br /&amp;gt; Le script a traité 4 lignes dont 2(=2) lignes vides ou commençant par un #&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Divers ===&lt;br /&gt;
&lt;br /&gt;
awk permet, bien sûr l&#039;utilisation de :&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;if (condition) {instructions} else {instructions}&amp;lt;/code&amp;gt; : si alors sinon&lt;br /&gt;
* &amp;lt;code&amp;gt;while (condition) {instructions}&amp;lt;/code&amp;gt; : boucle tantque&lt;br /&gt;
* &amp;lt;code&amp;gt;do {instructions} while ()&amp;lt;/code&amp;gt; : boucle répéter jusqu&#039;à&lt;br /&gt;
* &amp;lt;code&amp;gt;for (expr1; expr2; expr3) {instructions}&amp;lt;/code&amp;gt; : boucle pour &lt;br /&gt;
* &amp;lt;code&amp;gt;for (var in tableau)&amp;lt;/code&amp;gt; : boucle pour toutes les valeur du tableau. Il existe aussi while (var ni tableau), if (var in tableau) ...&lt;br /&gt;
&lt;br /&gt;
== Utiliser awk ==&lt;br /&gt;
&lt;br /&gt;
=== Par la ligne de commande ===&lt;br /&gt;
&lt;br /&gt;
Il existe deux façons de se servir de awk en tapant la commande awk suivie d&#039;arguments.&amp;lt;br /&amp;gt;&#039;&#039;&#039;La première&#039;&#039;&#039; consiste à saisir le code à exécuter directement sur la ligne de commande, celà convient parfaitement à de petits scripts. La syntaxe est la suivante : &amp;lt;code&amp;gt;awk -F séparateur_de_champ &#039;script awk&#039; fichiers_a_traiter&amp;lt;/code&amp;gt;, par exemple &amp;lt;code&amp;gt;awk -F &#039;:&#039; &#039;{ print $1 &amp;quot; est &amp;quot; $5 }&#039; /etc/passwd&amp;lt;/code&amp;gt;.&amp;lt;br /&amp;gt;&#039;&#039;&#039;La seconde&#039;&#039;&#039; consiste à placer votre script dans un fichier et à l&#039;appeler par la commande &amp;lt;code&amp;gt;awk -f fichier_script fichier_a_traiter&amp;lt;/code&amp;gt; vous pouvez définir le séparateur de champ dans votre script, dans la section BEGIN ou le spécifier sur la ligne de commande grâce à l&#039;option -F, comme ci-dessus. L&#039;exemple ci-dessus deviendrait alors &amp;lt;code&amp;gt;awk -f monScript /etc/passwd&amp;lt;/code&amp;gt; ou monScript serait : &amp;lt;tt&amp;gt;BEGIN { FS = &amp;quot;:&amp;quot;}&amp;lt;br /&amp;gt; { print $1 &amp;quot; est &amp;quot; $5 }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; &#039;&#039;&#039;ou bien&#039;&#039;&#039; &amp;lt;code&amp;gt;awk -F &#039;:&#039; -f monScript2 /etc/passwd&amp;lt;/code&amp;gt; avec monScript2 valant &amp;lt;tt&amp;gt;{ print $1 &amp;quot; est &amp;quot; $5 }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; &#039;&#039;&#039;Notez&#039;&#039;&#039; que dans le script on doit saisir FS = &amp;quot;:&amp;quot; et non FS = &#039;:&#039;. &#039;&#039;&#039;Vous êtes prévenus !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Comme d&#039;habitude, pour les autres options de la ligne de commande, je vous renvoie à la page de manuel de awk.&lt;br /&gt;
&lt;br /&gt;
=== Des scripts exécutables ===&lt;br /&gt;
&lt;br /&gt;
Cette utilisation a vite quelque chose de rébarbatif quand même, on rend donc les scripts directement exécutables en plaçant en en-tête &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;#!/bin/awk -f&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (le chemin doit être adapté à l&#039;emplacement de awk). Créons donc un fichier monScript3 dans lequel nous plaçons : &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;#!/bin/awk -f&amp;lt;/nowiki&amp;gt;&amp;lt;br /&amp;gt; BEGIN { FS = &amp;quot;:&amp;quot;}&amp;lt;br /&amp;gt; { print $1 &amp;quot; est &amp;quot; $5 }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; Suite à cette saisie, on rend le script exécutable par &amp;lt;code&amp;gt;chmod a+x&amp;lt;/code&amp;gt; et on exécute par &amp;lt;code&amp;gt;./monScript3 /etc/passwd&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A partir de maintenant, j&#039;estime que vous avez les bases nécessaires pour réaliser vos scripts, si awk vous intéresse. Je vais maintenant vous soumettre des exemples qui vous aideront à mieux comprendre les choses qui sont peut être restées obscures lors de cette présentation sommaire. N&#039;oubliez pas que le bon réflexe en cas de problème reste de lire la doc. En cas de gros pépin, postez un message dans le forum de lea-linux, je ne suis jamais loin ou envoyez moi un mail (j&#039;y réponds dès que j&#039;ai le temps).&lt;br /&gt;
&lt;br /&gt;
== Des filtres en exemple ==&lt;br /&gt;
&lt;br /&gt;
=== Transformer le fichier hosts ===&lt;br /&gt;
&lt;br /&gt;
Si vous êtes des habitués du site, ce premier exemple vous rapellera peut être quelque chose puisque je l&#039;avais posté dans le forum en réponse à une personne qui souhaitait adapter le format des IP du fichier hosts à ses besoins, xxx.xxx.xxx.xxx.&amp;lt;br /&amp;gt;&#039;&#039;&#039;&#039;&#039;Voici donc le code du premier filtre exemple :&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;#!/usr/bin/awk -f&amp;lt;/nowiki&amp;gt;&amp;lt;br /&amp;gt; !(/^#/ || /^$/) {&amp;lt;br /&amp;gt; split ($1, array_ip, &amp;quot;.&amp;quot;)&amp;lt;br /&amp;gt; printf &amp;quot;%03d.%03d.%03d.%03d\t%s\t%s\n&amp;quot;, array_ip[1], array_ip[2], array_ip[3], array_ip[4],$2,$3&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La première ligne signifie qu&#039;on va chercher awk dans le répertoire /usr/bin/, ce qui est le bon chemin pour ma slack.&amp;lt;br /&amp;gt; La deuxiême ligne signifie qu&#039;on ne s&#039;intéresse qu&#039;aux lignes qui ne commencent pas par un # ni aux lignes vides. En effet en expressions régulières, &amp;lt;code&amp;gt;^&amp;lt;/code&amp;gt; signifie &amp;lt;code&amp;gt;début de chaîne&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;fin de chaîne&amp;lt;/code&amp;gt;.&amp;lt;br /&amp;gt; Par la suite, on découpe le premier paramètre en prenant comme séparateur le &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt;, on stocke le résultat dans un tableau et on affiche les données du tableau en les formattant puis les autres champs (nom_de_machine et nom_de_machine.domaine). Le formatage %03d signifie qu&#039;on affiche des entiers sur trois caractères et que s&#039;il manque des caractères, on précède ceux qui existent avec des 0.&amp;lt;br /&amp;gt; Il faut rendre ce script exécutable : &amp;lt;code&amp;gt;chmod a+x prepare_hosts.awk&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt; Puis, on l&#039;appelle comme ça : &amp;lt;code&amp;gt;./prepare_hosts.awk /etc/hosts &amp;gt; hosts.prepared&amp;lt;/code&amp;gt; pour récupérer le fichier traité dans un fichier hosts.prepared placé dans le répertoire en cours.&lt;br /&gt;
&lt;br /&gt;
=== Filtre de GéoConcept© vers GRASS(GNU/GPL) ===&lt;br /&gt;
&lt;br /&gt;
GéoConcept et GRASS sont deux systèmes d&#039;information géographique (je dirais SIG par la suite). GéoConcept permet d&#039;exporter des objets surfaces selon une syntaxe explicitée ci-dessous. Le fichier export de GéoConcept contient tous les objets exportés.&lt;br /&gt;
&lt;br /&gt;
Bien entendu ce format n&#039;est pas du tout celui de GRASS qui est explicité ci-après, j&#039;ai donc du écrire un p&#039;tit filtre. Il n&#039;est pas universel puisqu&#039;on ne sait pas combien de champs se trouvent avant les coordonnées avant de faire l&#039;export dans GéoConcept. Je le donne ici à titre d&#039;exemple et j&#039;y ai fait de grosses découpes, ne l&#039;utilisez pas tel quel. Si vous êtes arrivés ici en faisant une recherche sur les SIG et que ce script vous intéresse, je peux vous l&#039;envoyer par mail.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Format GéoConcept :&#039;&#039;&#039;&amp;lt;br /&amp;gt;&amp;lt;tt&amp;gt;//$SYSCOORD {Type:1}&amp;lt;br /&amp;gt; //$UNIT Distance:m&amp;lt;br /&amp;gt; //$FORMAT 1&amp;lt;br /&amp;gt; 28878 buffer comm TRITTELING 911561.09 2462669.95 69 0. 1.e-002 ...&amp;lt;br /&amp;gt; 28595 buffer comm LONGWY 848138.94 2509824.85 91 45.62 -171.88 ...&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; Soit en clair :&lt;br /&gt;
&lt;br /&gt;
* 3 lignes inutiles pour nous.&lt;br /&gt;
* L&#039;identifiant GéoConcept de l&#039;objet&lt;br /&gt;
* Le type d&#039;objet&lt;br /&gt;
* Le sous-type d&#039;objet&lt;br /&gt;
* Les champs qu&#039;on a demandé à exporter, ici le nom de l&#039;objet et c&#039;est tout&lt;br /&gt;
* Les coordonnées absolues x et y du premier point du contour de la surface&lt;br /&gt;
* Le nombre de points décrivant le contour&lt;br /&gt;
* Les coordonnées relatives entre chaque point&lt;br /&gt;
* Le nombre de trous&lt;br /&gt;
* Les coordonnées absolues x et y du premier point du contour du trou&lt;br /&gt;
* Le nombre de points décrivant le contour du trou&lt;br /&gt;
* Les coordonnées relatives entre chaque point du contour du trou&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Format GRASS :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;14 lignes d&#039;en-tête comprenant des renseignements divers&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; A 69&amp;lt;br /&amp;gt; 2462669.95 911561.09&amp;lt;br /&amp;gt; 2462669.96 911561.09&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; Soit en clair :&lt;br /&gt;
&lt;br /&gt;
* 11 lignes inutiles pour nous, recollées directement d&#039;un header.&lt;br /&gt;
* A 25 : pour dire que c&#039;est une surface (area) et que son contour comporte 25 points&lt;br /&gt;
* Les coordonnées absolues y et x des points du contour de la surface&lt;br /&gt;
* Les mêmes renseignements pour les trous&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Les bouts intéressants du script&#039;&#039;&#039; &amp;lt;tt&amp;gt; BEGIN {&amp;lt;br /&amp;gt; melange = &amp;quot;v.patch input=&amp;quot;&amp;lt;br /&amp;gt; exited = 0&amp;lt;br /&amp;gt; getline h1 &amp;lt; &amp;quot;header&amp;quot;&amp;lt;br /&amp;gt; getline h2 &amp;lt; &amp;quot;header&amp;quot;&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; !/\/\// {&amp;lt;br /&amp;gt; print h1 &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1&amp;lt;br /&amp;gt; print h2 &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; melange = melange $1 &amp;quot;.awkImport,&amp;quot;&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; beginObj = 5&amp;lt;br /&amp;gt; if ( (beginObj + 2 + $(beginObj+2) * 2) &amp;lt; NF) {&amp;lt;br /&amp;gt; nbTrou = $((beginObj+3) + $(beginObj+2) * 2)&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; else {&amp;lt;br /&amp;gt; nbTrou = 0&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; for ( i=0 ; i &amp;lt; nbTrou+1 ; i++) {&amp;lt;br /&amp;gt; actualx = $beginObj&amp;lt;br /&amp;gt; actualy = $(beginObj+1)&amp;lt;br /&amp;gt; print &amp;quot;A &amp;quot; ($(beginObj+2)+2) &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1&amp;lt;br /&amp;gt; print &amp;quot; &amp;quot; actualy &amp;quot; &amp;quot; actualx &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; for ( j=(beginObj+3) ; j&amp;lt;(beginObj+3)+$(beginObj+2)*2-1 ; j++ ) {&amp;lt;br /&amp;gt; actualx += $j&amp;lt;br /&amp;gt; actualy += $(++j)&amp;lt;br /&amp;gt; print &amp;quot; &amp;quot; actualy &amp;quot; &amp;quot; actualx &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; print &amp;quot; &amp;quot; $(beginObj+1) &amp;quot; &amp;quot; $beginObj &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; fflush (ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1)&amp;lt;br /&amp;gt; close (ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1)&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; if ( system(&amp;quot;v.support map=&amp;quot; $1 &amp;quot;.awkImport option=build -s threshold=&amp;quot; thresh &amp;quot; &amp;gt;/dev/null&amp;quot;)!=0 )&amp;lt;br /&amp;gt; exit (1)&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; END {&amp;lt;br /&amp;gt; print &amp;quot;Patching all files into composite.awkImport&amp;quot;&amp;lt;br /&amp;gt; if ( system (melange &amp;quot; output=composite.awkImport&amp;quot; ) != 0 )&amp;lt;br /&amp;gt; exit (1)&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; for (i=1;i&amp;lt;=FNR;i++) {&amp;lt;br /&amp;gt; getline &amp;lt; ARGV[1]&amp;lt;br /&amp;gt; print i &amp;quot;:&amp;quot; $4 &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_cats/&amp;quot; mapName&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; system (effaceTempos &amp;quot; &amp;gt; /dev/null&amp;quot;)&amp;lt;br /&amp;gt; fflush ()&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons ensemble analyser les morceaux intéressants de ce script.&lt;br /&gt;
&lt;br /&gt;
Tout d&#039;abord, je définis quelques variables dans la section BEGIN, qui restent accessibles jusqu&#039;à la fin de l&#039;exécution. Ensuite j&#039;affecte des valeurs aux variables h1 et h2 en lisant les lignes dans un fichier du répertoire courant nommé &amp;lt;code&amp;gt;header&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Pour chaque objet (tout ce qui ne commence pas par //), j&#039;insère un entête GRASS, composé des variables h1, h2, etc... que je range dans un fichier avec le symbole de redirection &amp;lt;code&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; dont le chemin est la concaténation de la variable d&#039;environnement LOCATION (&amp;lt;code&amp;gt;ENVIRON[&amp;quot;LOCATION&amp;quot;]&amp;lt;/code&amp;gt;), de la chaîne &amp;lt;code&amp;gt;&amp;quot;/dig_ascii/&amp;quot;&amp;lt;/code&amp;gt; et de la première colonne de la ligne que je suis en train de lire (&amp;lt;code&amp;gt;$1&amp;lt;/code&amp;gt;).&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;ajoute à la variable &amp;lt;code&amp;gt;melange&amp;lt;/code&amp;gt; une chaine constituée de ma variable &amp;lt;code&amp;gt;$1&amp;lt;/code&amp;gt; et de la chaine &amp;lt;code&amp;gt;&amp;quot;.awkImport&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je dis que les coordonnées de l&#039;objet commencent à la colonne 5. Ceci me dit (voir explications du format GC ci-dessus) que si il y a des trous, c&#039;est à dire si la somme du double du nombre de points intermédiaires donné en colonne 7 (&amp;lt;code&amp;gt;$(beginObj+2)&amp;lt;/code&amp;gt; équivaut à &amp;lt;code&amp;gt;$7&amp;lt;/code&amp;gt; car &amp;lt;code&amp;gt;beginObj&amp;lt;/code&amp;gt; vaut 5)+ les cinq colonnes de départ + 2 pour les 2 premières coordonnées absolues est inférieur au nombre total de colonnes de la ligne contenu dans la variable &amp;lt;code&amp;gt;NF&amp;lt;/code&amp;gt;, alors leur nombre me serra donné à la colonne suivant ce nombre de colonnes précalculé, d&#039;où le &amp;lt;code&amp;gt;nbTrous = $((beginObj+3) + $(beginObj+2) * 2)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ensuite la reconstitution des coordonnées absolues et l&#039;inscription dans le fichier utilisé plus haut donne l&#039;occasion de voir la syntaxe des boucles &amp;lt;code&amp;gt;for&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On flushe le buffer du fichier et on le ferme. Au début j&#039;avais oublié, alors, je me suis retrouvé avec BEAUCOUP TROP de fichiers ouverts. Vous me direz, le fichier je l&#039;ai pas ouvert. Bé, oui, c&#039;est le côté expérimentation hasardeuse qui m&#039;a fait comprendre. M&#039;enfin, vous pourrez pas dire : &amp;quot;euh, ben, je comprends pas pourquoi mon linux me dit que le script il doit s&#039;arrêter à cause que j&#039;ai un problème de ressources&amp;quot;.&amp;lt;br /&amp;gt; Ceci dit, je peux me tromper aussi. Si j&#039;ai tort envoyez moi un mail.&lt;br /&gt;
&lt;br /&gt;
La ligne suivante nous donne un exemple d&#039;utilisation de la commande system, avec récupération du code de retour et aussi de la commande exit. RAS.&lt;br /&gt;
&lt;br /&gt;
La suite montre l&#039;utilisation de variables telles que FNR, ARGV ainsi que des appels à la fonction système avec redirection et l&#039;utilisation des variables déclarées dans le begin et que l&#039;on a fait évoluer au cours du script.&lt;br /&gt;
&lt;br /&gt;
== Le mot de la fin, enfin ;-) ==&lt;br /&gt;
&lt;br /&gt;
Voilà, j&#039;espère vous avoir fait comprendre ce qu&#039;était awk et à quoi il servait. Bien sûr on peut faire la même chose en Perl, PHP, C, Java. Je sais. Mais utiliser awk plutôt que Perl quand il est adapté c&#039;est un peu comme aller dans un petit hôtel/restaurant pittoresque plutôt que d&#039;aller au Club Med. En plus, awk est très léger et peut être un allié puissant dans les systèmes embarqués.&lt;br /&gt;
&lt;br /&gt;
Nota : Je vous ai généré un pdf du manuel de awk accessible [awk.pdf ici] (64ko). Petit rappel en passant : la manipulation pour générer des pdf à partir des pages de manuel se trouve sur [http://lea-linux.org Léa] section [../trucs Trucs et astuces], rubrique [/trucs/sommaire.php3?cat=6 Shell].&lt;br /&gt;
&lt;br /&gt;
a+&amp;lt;br /&amp;gt; Xavier&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;merci&amp;quot;&amp;gt;Cette page est issue de la documentation &#039;pré-wiki&#039; de Léa a été convertie avec HTML::WikiConverter. Elle fut créée par Xavier GARREAU le 18/04/2001.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Copyright =&lt;br /&gt;
Copyright &amp;amp;copy; 18/04/2001, Xavier GARREAU&lt;br /&gt;
{{CC-BY-NC-SA}}&lt;/div&gt;</summary>
		<author><name>BernardTV</name></author>
	</entry>
	<entry>
		<id>https://lea-linux.org/docs/index.php?title=GAWK&amp;diff=11185</id>
		<title>GAWK</title>
		<link rel="alternate" type="text/html" href="https://lea-linux.org/docs/index.php?title=GAWK&amp;diff=11185"/>
		<updated>2005-12-21T13:32:59Z</updated>

		<summary type="html">&lt;p&gt;BernardTV : /* Qu&amp;#039;est ce que c&amp;#039;est */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Développer sous Linux]]&lt;br /&gt;
= Introduction à (g)awk =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;leatitre&amp;quot;&amp;gt;Introduction à (g)awk&amp;lt;/div&amp;gt;&amp;lt;div class=&amp;quot;leapar&amp;quot;&amp;gt;par [mailto:xgarreau@club-internet.fr Xavier GARREAU]&amp;lt;/div&amp;gt;&amp;lt;div class=&amp;quot;leadesc&amp;quot;&amp;gt;Cet article va vous permettre de vous familiariser avec (g)awk, langage de programmation permettant de faire très rapidement des traitements intéressants sur des données diverses. Après la présentation générale, on réalisera deux filtres inspirés de filtres ayant été réellement développés.&amp;lt;/div&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
=== Présentation ===&lt;br /&gt;
&lt;br /&gt;
Vous vous demandez surement pourquoi ce (g) avant awk, non ? Ce n&#039;est pas le g de gnome, ni celui de gtk+ mais celui de gnu. Extrait de la page de manuel (&amp;lt;code&amp;gt;man gawk&amp;lt;/code&amp;gt; ou &amp;lt;code&amp;gt;man awk&amp;lt;/code&amp;gt;) :&amp;lt;br /&amp;gt;&#039;&#039;&amp;quot;Gawk est l&#039;implémentation du projet GNU du langage de programmation AWK, lequel se conforme à la définition du langage dans la norme &#039;&#039;&#039;POSIX1003.2 Command Language and Utilities Standard&#039;&#039;&#039;. Cette version est basée, elle, sur la description d&#039;AWK de Aho, Kernighan and Weinberger, plus les spécificités supplémentaires se trouvant dans la version de awk de l&#039;UNIX System V version 4. Gawk ajoute également des extensions plus récentes des Laboratoires Bell ainsi que des extensions spécifiques à GNU.&amp;quot;&#039;&#039;&amp;lt;br /&amp;gt; Je ne mets pas ce pavé pour remplir de l&#039;espace mais pour que les personnes à la base de choses que je ne fais que présenter soient reconnues pour leur travail et que l&#039;on sache de quoi on parle.&lt;br /&gt;
&lt;br /&gt;
Nous allons pouvoir commencer:&lt;br /&gt;
&lt;br /&gt;
=== Qu&#039;est ce que c&#039;est ===&lt;br /&gt;
&lt;br /&gt;
awk (j&#039;utiliserai awk par la suite, mais c&#039;est de gawk que l&#039;on parle) est un langage interprété, installé par défaut sur les distributions linux (au moins rh et mandrake) dans le répertoire /bin. Il permet de traiter des fichiers de données structurées.&amp;lt;br /&amp;gt; Un programme awk est une suite de blocs de code compris entre {} (c&#039;est pas très original) qui sont appliqués aux lignes (par défaut) de données du fichier si un &amp;quot;modèle&amp;quot; est vérifié. La page de manuel nous donne les différents types de modèles utilisables : &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
| &amp;lt;code&amp;gt; BEGIN &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté au début du programme, &#039;&#039;&#039;une seule fois&#039;&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; END &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté à la fin du programme, &#039;&#039;&#039;une seule fois&#039;&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; /expression régulière/ &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté si les données en cours de traitement correspondent à l&#039;expression régulière. Si vous ne connaissez pas les expressions régulières, lisez la page &amp;lt;code&amp;gt;man egrep&amp;lt;/code&amp;gt;.&amp;lt;br /&amp;gt;&#039;&#039;&#039;Un exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;/^#/&amp;lt;/code&amp;gt; Permet de selectionner les lignes commençant par un #.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; expression relationnelle &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté si l&#039;expression est vraie.&amp;lt;br /&amp;gt;&#039;&#039;&#039;Un exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;maVariable==5&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; modèle &amp;amp;&amp;amp; modèle &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté si les deux modèles sont vérifiés.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; modèle || modèle &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté si au moins un des modèles est vérifié.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; modèle0 ? modèle1 : modèle2 &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté si les modèles 0 et 1 sont vérifiés ou si le modèle2 uniquement est vérifié.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; (modèle) &amp;lt;/code&amp;gt;&lt;br /&gt;
| Permet de grouper les modèles.&amp;lt;br /&amp;gt; Un exemple : &amp;lt;code&amp;gt;(modèle0 || modèle1) &amp;amp;&amp;amp; modèle2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; ! modèle &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté si le modèle n&#039;est pas vérifié.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt; modèle1, modèle2 &amp;lt;/code&amp;gt;&lt;br /&gt;
| Le bloc qui suit est exécuté pour la partie des données en cours commençant par modèle1 et finissant par modèle2.&amp;lt;br /&amp;gt;&#039;&#039;&#039;Un exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;/\/\*/, /\*\//&amp;lt;/code&amp;gt; pour afficher les commentaires multilignes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Premiers pas ==&lt;br /&gt;
&lt;br /&gt;
=== Les enregistrements ===&lt;br /&gt;
&lt;br /&gt;
Pour awk, les blocs de données lues sont séparés par un caractère contenu dans la variable &#039;&#039;&#039;RS&#039;&#039;&#039; (Record Separator, retour à la ligne par défaut). On peut accéder à l&#039;intégralité du bloc grâce à la variable &#039;&#039;&#039;$0&#039;&#039;&#039;. C&#039;est ce qu&#039;on appelle un enregistrement.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Un exemple&#039;&#039;&#039; : Tapez &amp;lt;code&amp;gt;awk &#039;{ print $0 }&#039; un_fichier&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt; Passionant, non ? vous venez de réinventer la commande &amp;lt;code&amp;gt;cat&amp;lt;/code&amp;gt; ;-) ! &amp;lt;br /&amp;gt;&#039;&#039;&#039;Un autre exemple&#039;&#039;&#039; : Tapez &amp;lt;code&amp;gt;awk &#039;/\/\*/, /\*\// { print $0 }&#039; un_fichier_c_avec_des_commentaires&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt; C&#039;est déjà plus sympa, hein ? &amp;lt;br /&amp;gt;&#039;&#039;&#039;Un dernier exemple&#039;&#039;&#039; : Tapez &amp;lt;code&amp;gt;awk &#039;! (/^ *#/ || /^$/) { print $0 }&#039; un_fichier_conf&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt; Vous n&#039;aviez jamais vu votre fichier de config d&#039;Apache comme ça, si ?&lt;br /&gt;
&lt;br /&gt;
=== Les champs ===&lt;br /&gt;
&lt;br /&gt;
Ah, la nature ... Courir nus dans les champs en se tenant la main ... &#039;&#039;&#039;NON&#039;&#039;&#039;, je vous arrête tout de suite.&amp;lt;br /&amp;gt; Chaque enregistrement est séparé en champs par un caractère contenu dans la variable FS (Field Separator, un espace par défaut). Les champs sont accessibles par les variables $1, $2, $3, etc ...&amp;lt;br /&amp;gt;Pour afficher le 3&amp;lt;sup&amp;gt;ème&amp;lt;/sup&amp;gt; champ de toutes les lignes de vos données à traiter, vous utilisez &amp;lt;code&amp;gt;print $3&amp;lt;/code&amp;gt;.&amp;lt;br /&amp;gt;&#039;&#039;&#039;Un exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;awk -F &#039;:&#039; &#039;{ print $1 &amp;quot; est &amp;quot; $5 }&#039; /etc/passwd&amp;lt;/code&amp;gt; pour afficher la description des utilisateurs de votre machine.&lt;br /&gt;
&lt;br /&gt;
=== Les variables ===&lt;br /&gt;
&lt;br /&gt;
Il existe bon nombre de variables prédéfinies en awk. Je vais vous en donner la liste résumée, encore une fois, je n&#039;invente rien et je ne créée rien, je ne fais que vous refaire une lecture de la page de manuel. D&#039;ailleurs pour avoir une liste exhaustive des variables, consultez la.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
| ARGC&lt;br /&gt;
| Si vous avez fait du c, vous vous en doutez ! Sinon, je vous le dis. Cette variable contient le nombre d&#039;arguments passés &#039;&#039;&#039;au programme. (sans les options passées à awk)&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| ARGV&lt;br /&gt;
| Un tableau contenant les &#039;&#039;ARGC&#039;&#039; paramètres, indéxé de 0 à ARGC-1. Ce sont tous les fichiers à traiter&lt;br /&gt;
|-&lt;br /&gt;
| CONVFMT&lt;br /&gt;
| Le format par défaut pour l&#039;affichage des nombres, &amp;quot;%.6g&amp;quot; par défaut&lt;br /&gt;
|-&lt;br /&gt;
| ENVIRON&lt;br /&gt;
| Un tableau contenant les variables d&#039;environnement. &#039;&#039;&#039;Exemple&#039;&#039;&#039; &amp;lt;code&amp;gt;ENVIRON[&amp;quot;PATH&amp;quot;]&amp;lt;/code&amp;gt; contient votre path.&lt;br /&gt;
|-&lt;br /&gt;
| FIELDWIDTHS&lt;br /&gt;
| Pour le cas de traitement de données non délimités mais contenant des champs de largeur fixe.&amp;lt;br /&amp;gt; Cette variable est de la forme &amp;lt;code&amp;gt;largeur_champ_1 largeur_champ_2 largeur_champ_3 etc...&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| FNR&lt;br /&gt;
| Le numéro de l&#039;enregistrement actuellement en cours de traitement.&amp;lt;br /&amp;gt;&#039;&#039;&#039;Un exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;awk &#039;{print FNR &amp;quot;: &amp;quot; $0}&#039; un_fichier&amp;lt;/code&amp;gt; permet d&#039;afficher le fichier avec les numéros de lignes.&amp;lt;br /&amp;gt;&#039;&#039;&#039;Un autre exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;awk &#039;{print FNR &amp;quot;: &amp;quot; $0}&#039; un_fichier | grep ^45:&amp;lt;/code&amp;gt; permet d&#039;afficher la ligne 45 du fichier &#039;&#039;un_fichier&#039;&#039;. On fait appel à grep, ce n&#039;est plus du 100% awk mais c&#039;est beau la diversité, non ?&lt;br /&gt;
|-&lt;br /&gt;
| FS&lt;br /&gt;
| Le séparateur de champs. No comment !&lt;br /&gt;
|-&lt;br /&gt;
| IGNORECASE&lt;br /&gt;
| En gros, permet de ne pas prendre en compte la casse lors des comparaisons de chaines de caractères entre elles où avec des expressions régulières. Voir la page de manuel pour les détails.&lt;br /&gt;
|-&lt;br /&gt;
| NF&lt;br /&gt;
| Norme Française ... NON, Number of fields : C&#039;est le nombre de champs de l&#039;enregistrement en cours.&lt;br /&gt;
|-&lt;br /&gt;
| NR&lt;br /&gt;
| Number of Records : Le nombre d&#039;enregistrements traités jusqu&#039;à maintenant.&lt;br /&gt;
|-&lt;br /&gt;
| RS&lt;br /&gt;
| Le séparateur d&#039;enregistrements. No comment !&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bien entendu, vous pouvez également définir les vôtres.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Exemples :&#039;&#039;&#039;&lt;br /&gt;
: &amp;lt;code&amp;gt;maVar=3&amp;lt;/code&amp;gt; déclare et initialise la variable myVar à la valeur 3.&amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;print maVar&amp;lt;/code&amp;gt; affiche le &#039;&#039;&#039;contenu de la variable maVar&#039;&#039;&#039;.&amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;print $maVar&amp;lt;/code&amp;gt; affiche le &#039;&#039;&#039;champ n°maVar&#039;&#039;&#039; de l&#039;enregistrement en cours (ici, &#039;&#039;&#039;équivaut à print $3&#039;&#039;&#039;).&amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;print $(maVar-1)&amp;lt;/code&amp;gt; affiche le &#039;&#039;&#039;champ n°(maVar-1)&#039;&#039;&#039; de l&#039;enregistrement en cours (ici, &#039;&#039;&#039;équivaut à print $2&#039;&#039;&#039;).&amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;split(&amp;quot;toto:tata:titi:tutu&amp;quot;, arr, &amp;quot;:&amp;quot;)&amp;lt;/code&amp;gt; initialise le tableau arr à (&amp;quot;toto&amp;quot;,&amp;quot;tata&amp;quot;,...). On accède ensuite aux valeurs par &amp;lt;code&amp;gt;arr[1], arr[2], ..., arr[4]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Les fonctions ===&lt;br /&gt;
&lt;br /&gt;
Il y en a de nombreuses : &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour l&#039;affichage formaté, de textes et de nombres. &amp;lt;code&amp;gt;&#039;&#039;&#039;print printf ...&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* pour les opérations habituelles sur les chaines de caractères, concaténation, substitution, remplacement, recherche ... &amp;lt;code&amp;gt;&#039;&#039;&#039;gensub substr tolower index split ...&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* pour les accés aux systèmes de fichiers et au système &amp;lt;code&amp;gt;&#039;&#039;&#039;fflush close nextline system&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* pour les fonctions mathématiques &amp;lt;code&amp;gt;&#039;&#039;&#039;rand sin exp log ...&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* pour la gestion du temps &amp;lt;code&amp;gt;&#039;&#039;&#039;systime strftime&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Les possibilités de formatage importantes à votre disposition sont définies dans la page de manuel de awk.&lt;br /&gt;
&lt;br /&gt;
Et vous pouvez également définir vos fonctions grâce à la syntaxe : &amp;lt;tt&amp;gt; function nom_de_fonction(param1, param2, var_locale_1, var_locale_2) {&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; ou &amp;lt;tt&amp;gt; func nom_de_fonction(param1, param2 var_locale_1, var_locale_2) {&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; La déclaration des variables locales est étrange. Celà vient du fait que awk n&#039;était pas prévu pour permettre la créaton de fonctions. Il a donc été décidé, de les ajouter à la liste des paramètres, mais séparées par des espaces supplémentaires. L&#039;appel de la fonction, lui, ne contient que les paramètres. &#039;&#039;&#039;Exemple&#039;&#039;&#039; : &amp;lt;code&amp;gt;nom_de_fonction(5,2)&amp;lt;/code&amp;gt;. Les variables locales sont initialisées à chaine vide ou zéro.&lt;br /&gt;
&lt;br /&gt;
=== Blocs ===&lt;br /&gt;
&lt;br /&gt;
Merci à Jean-Louis pour m&#039;avoir montré que je n&#039;insistais pas assez sur le fonctionnement des blocs. C&#039;est grâce à lui que cette partie existe&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Utilisation des blocs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Prenons un exemple :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;#!/usr/bin/awk -f&amp;lt;/nowiki&amp;gt;&amp;lt;br /&amp;gt; BEGIN {&amp;lt;br /&amp;gt; print &amp;quot;début du script&amp;quot;&amp;lt;br /&amp;gt; maVariable=5&amp;lt;br /&amp;gt; nbLignes=0&amp;lt;br /&amp;gt; nbCommentaires=0&amp;lt;br /&amp;gt; nbCommentaires2=0&amp;lt;br /&amp;gt; print &amp;quot;maVariable vaut &amp;quot; maVariable&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; ( /^#/ || /^$/ ) {&amp;lt;br /&amp;gt; nbCommentaires++&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; {&amp;lt;br /&amp;gt; nbLignes++&amp;lt;br /&amp;gt; printf &amp;quot;%04d:%s\n&amp;quot;,FNR,$0&amp;lt;br /&amp;gt; if ( $0 ~ /^#/ || $0 ~ /^$/ ) {&amp;lt;br /&amp;gt; nbCommentaires2++&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; END {&amp;lt;br /&amp;gt; print &amp;quot;fin du script maVariable vaut toujours &amp;quot; maVariable&amp;lt;br /&amp;gt; print &amp;quot;Le script a traité &amp;quot; FNR &amp;quot; lignes dont &amp;quot; nbCommentaires &amp;quot;(=&amp;quot; nbCommentaires2 &amp;quot;) lignes vides ou commençant par un #&amp;quot;&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Explications :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Le bloc BEGIN est exécuté &#039;&#039;&#039;une fois&#039;&#039;&#039; au début, &#039;&#039;&#039;avant le traitement des données&#039;&#039;&#039;. Il affiche &amp;quot;début du script&amp;quot;, initialise les variables et affiche le contenu de &amp;lt;code&amp;gt;maVariable&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Un bloc qui est exécuté pour chaque ligne commençant par un # ou vide, il incrémente la variable nbCommentaires.&lt;br /&gt;
* Un Bloc exécuté pour toutes les lignes, il incrémente la variable &amp;lt;code&amp;gt;nbLignes&amp;lt;/code&amp;gt;, affiche la ligne préfixée par son numéro. Le numéro est formaté pour occupper quattre caractères. Les lignes suivantes (à partir du &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;) montrent l&#039;équivalence entre le bloc du dessus et un test if dans le bloc principal. La variable nbCommentaires2 est incrémentée pour chaque ligne commençant par un dièse ou vide.&lt;br /&gt;
* Le bloc END est exécuté &#039;&#039;&#039;une fois&#039;&#039;&#039; à la fin, &#039;&#039;&#039;après le traitement des données&#039;&#039;&#039;. On voit que la variable &amp;lt;code&amp;gt;maVariable&amp;lt;/code&amp;gt; est toujours définie et que son contenu n&#039;a pas été altéré. Il indique également le nombre total de lignes traitées et le nombre de lignes de commentaires ou vides présentes dans le fichier.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exécution&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;# chmod a+x ceScript.awk&amp;lt;/nowiki&amp;gt;&amp;lt;br /&amp;gt; # ./ceScript.awk unfichier.shell&amp;lt;br /&amp;gt; début du script&amp;lt;br /&amp;gt; maVariable vaut 5&amp;lt;br /&amp;gt; 0001:# Ce script affiche hello world&amp;lt;br /&amp;gt; 0002:&amp;lt;br /&amp;gt; 0003:echo &amp;quot;hello world&amp;quot;&amp;lt;br /&amp;gt; 0004:exit 0&amp;lt;br /&amp;gt; fin du script maVariable vaut toujours 5&amp;lt;br /&amp;gt; Le script a traité 4 lignes dont 2(=2) lignes vides ou commençant par un #&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Divers ===&lt;br /&gt;
&lt;br /&gt;
awk permet, bien sûr l&#039;utilisation de :&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;if (condition) {instructions} else {instructions}&amp;lt;/code&amp;gt; : si alors sinon&lt;br /&gt;
* &amp;lt;code&amp;gt;while (condition) {instructions}&amp;lt;/code&amp;gt; : boucle tantque&lt;br /&gt;
* &amp;lt;code&amp;gt;do {instructions} while ()&amp;lt;/code&amp;gt; : boucle répéter jusqu&#039;à&lt;br /&gt;
* &amp;lt;code&amp;gt;for (expr1; expr2; expr3) {instructions}&amp;lt;/code&amp;gt; : boucle pour &lt;br /&gt;
* &amp;lt;code&amp;gt;for (var in tableau)&amp;lt;/code&amp;gt; : boucle pour toutes les valeur du tableau. Il existe aussi while (var ni tableau), if (var in tableau) ...&lt;br /&gt;
&lt;br /&gt;
== Utiliser awk ==&lt;br /&gt;
&lt;br /&gt;
=== Par la ligne de commande ===&lt;br /&gt;
&lt;br /&gt;
Il existe deux façons de se servir de awk en tapant la commande awk suivie d&#039;arguments.&amp;lt;br /&amp;gt;&#039;&#039;&#039;La première&#039;&#039;&#039; consiste à saisir le code à exécuter directement sur la ligne de commande, celà convient parfaitement à de petits scripts. La syntaxe est la suivante : &amp;lt;code&amp;gt;awk -F séparateur_de_champ &#039;script awk&#039; fichiers_a_traiter&amp;lt;/code&amp;gt;, par exemple &amp;lt;code&amp;gt;awk -F &#039;:&#039; &#039;{ print $1 &amp;quot; est &amp;quot; $5 }&#039; /etc/passwd&amp;lt;/code&amp;gt;.&amp;lt;br /&amp;gt;&#039;&#039;&#039;La seconde&#039;&#039;&#039; consiste à placer votre script dans un fichier et à l&#039;appeler par la commande &amp;lt;code&amp;gt;awk -f fichier_script fichier_a_traiter&amp;lt;/code&amp;gt; vous pouvez définir le séparateur de champ dans votre script, dans la section BEGIN ou le spécifier sur la ligne de commande grâce à l&#039;option -F, comme ci-dessus. L&#039;exemple ci-dessus deviendrait alors &amp;lt;code&amp;gt;awk -f monScript /etc/passwd&amp;lt;/code&amp;gt; ou monScript serait : &amp;lt;tt&amp;gt;BEGIN { FS = &amp;quot;:&amp;quot;}&amp;lt;br /&amp;gt; { print $1 &amp;quot; est &amp;quot; $5 }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; &#039;&#039;&#039;ou bien&#039;&#039;&#039; &amp;lt;code&amp;gt;awk -F &#039;:&#039; -f monScript2 /etc/passwd&amp;lt;/code&amp;gt; avec monScript2 valant &amp;lt;tt&amp;gt;{ print $1 &amp;quot; est &amp;quot; $5 }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; &#039;&#039;&#039;Notez&#039;&#039;&#039; que dans le script on doit saisir FS = &amp;quot;:&amp;quot; et non FS = &#039;:&#039;. &#039;&#039;&#039;Vous êtes prévenus !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Comme d&#039;habitude, pour les autres options de la ligne de commande, je vous renvoie à la page de manuel de awk.&lt;br /&gt;
&lt;br /&gt;
=== Des scripts exécutables ===&lt;br /&gt;
&lt;br /&gt;
Cette utilisation a vite quelque chose de rébarbatif quand même, on rend donc les scripts directement exécutables en plaçant en en-tête &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;#!/bin/awk -f&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (le chemin doit être adapté à l&#039;emplacement de awk). Créons donc un fichier monScript3 dans lequel nous plaçons : &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;#!/bin/awk -f&amp;lt;/nowiki&amp;gt;&amp;lt;br /&amp;gt; BEGIN { FS = &amp;quot;:&amp;quot;}&amp;lt;br /&amp;gt; { print $1 &amp;quot; est &amp;quot; $5 }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; Suite à cette saisie, on rend le script exécutable par &amp;lt;code&amp;gt;chmod a+x&amp;lt;/code&amp;gt; et on exécute par &amp;lt;code&amp;gt;./monScript3 /etc/passwd&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A partir de maintenant, j&#039;estime que vous avez les bases nécessaires pour réaliser vos scripts, si awk vous intéresse. Je vais maintenant vous soumettre des exemples qui vous aideront à mieux comprendre les choses qui sont peut être restées obscures lors de cette présentation sommaire. N&#039;oubliez pas que le bon réflexe en cas de problème reste de lire la doc. En cas de gros pépin, postez un message dans le forum de lea-linux, je ne suis jamais loin ou envoyez moi un mail (j&#039;y réponds dès que j&#039;ai le temps).&lt;br /&gt;
&lt;br /&gt;
== Des filtres en exemple ==&lt;br /&gt;
&lt;br /&gt;
=== Transformer le fichier hosts ===&lt;br /&gt;
&lt;br /&gt;
Si vous êtes des habitués du site, ce premier exemple vous rapellera peut être quelque chose puisque je l&#039;avais posté dans le forum en réponse à une personne qui souhaitait adapter le format des IP du fichier hosts à ses besoins, xxx.xxx.xxx.xxx.&amp;lt;br /&amp;gt;&#039;&#039;&#039;&#039;&#039;Voici donc le code du premier filtre exemple :&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;#!/usr/bin/awk -f&amp;lt;/nowiki&amp;gt;&amp;lt;br /&amp;gt; !(/^#/ || /^$/) {&amp;lt;br /&amp;gt; split ($1, array_ip, &amp;quot;.&amp;quot;)&amp;lt;br /&amp;gt; printf &amp;quot;%03d.%03d.%03d.%03d\t%s\t%s\n&amp;quot;, array_ip[1], array_ip[2], array_ip[3], array_ip[4],$2,$3&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La première ligne signifie qu&#039;on va chercher awk dans le répertoire /usr/bin/, ce qui est le bon chemin pour ma slack.&amp;lt;br /&amp;gt; La deuxiême ligne signifie qu&#039;on ne s&#039;intéresse qu&#039;aux lignes qui ne commencent pas par un # ni aux lignes vides. En effet en expressions régulières, &amp;lt;code&amp;gt;^&amp;lt;/code&amp;gt; signifie &amp;lt;code&amp;gt;début de chaîne&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;fin de chaîne&amp;lt;/code&amp;gt;.&amp;lt;br /&amp;gt; Par la suite, on découpe le premier paramètre en prenant comme séparateur le &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt;, on stocke le résultat dans un tableau et on affiche les données du tableau en les formattant puis les autres champs (nom_de_machine et nom_de_machine.domaine). Le formatage %03d signifie qu&#039;on affiche des entiers sur trois caractères et que s&#039;il manque des caractères, on précède ceux qui existent avec des 0.&amp;lt;br /&amp;gt; Il faut rendre ce script exécutable : &amp;lt;code&amp;gt;chmod a+x prepare_hosts.awk&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt; Puis, on l&#039;appelle comme ça : &amp;lt;code&amp;gt;./prepare_hosts.awk /etc/hosts &amp;gt; hosts.prepared&amp;lt;/code&amp;gt; pour récupérer le fichier traité dans un fichier hosts.prepared placé dans le répertoire en cours.&lt;br /&gt;
&lt;br /&gt;
=== Filtre de GéoConcept© vers GRASS(GNU/GPL) ===&lt;br /&gt;
&lt;br /&gt;
GéoConcept et GRASS sont deux systèmes d&#039;information géographique (je dirais SIG par la suite). GéoConcept permet d&#039;exporter des objets surfaces selon une syntaxe explicitée ci-dessous. Le fichier export de GéoConcept contient tous les objets exportés.&lt;br /&gt;
&lt;br /&gt;
Bien entendu ce format n&#039;est pas du tout celui de GRASS qui est explicité ci-après, j&#039;ai donc du écrire un p&#039;tit filtre. Il n&#039;est pas universel puisqu&#039;on ne sait pas combien de champs se trouvent avant les coordonnées avant de faire l&#039;export dans GéoConcept. Je le donne ici à titre d&#039;exemple et j&#039;y ai fait de grosses découpes, ne l&#039;utilisez pas tel quel. Si vous êtes arrivés ici en faisant une recherche sur les SIG et que ce script vous intéresse, je peux vous l&#039;envoyer par mail.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Format GéoConcept :&#039;&#039;&#039;&amp;lt;br /&amp;gt;&amp;lt;tt&amp;gt;//$SYSCOORD {Type:1}&amp;lt;br /&amp;gt; //$UNIT Distance:m&amp;lt;br /&amp;gt; //$FORMAT 1&amp;lt;br /&amp;gt; 28878 buffer comm TRITTELING 911561.09 2462669.95 69 0. 1.e-002 ...&amp;lt;br /&amp;gt; 28595 buffer comm LONGWY 848138.94 2509824.85 91 45.62 -171.88 ...&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; Soit en clair :&lt;br /&gt;
&lt;br /&gt;
* 3 lignes inutiles pour nous.&lt;br /&gt;
* L&#039;identifiant GéoConcept de l&#039;objet&lt;br /&gt;
* Le type d&#039;objet&lt;br /&gt;
* Le sous-type d&#039;objet&lt;br /&gt;
* Les champs qu&#039;on a demandé à exporter, ici le nom de l&#039;objet et c&#039;est tout&lt;br /&gt;
* Les coordonnées absolues x et y du premier point du contour de la surface&lt;br /&gt;
* Le nombre de points décrivant le contour&lt;br /&gt;
* Les coordonnées relatives entre chaque point&lt;br /&gt;
* Le nombre de trous&lt;br /&gt;
* Les coordonnées absolues x et y du premier point du contour du trou&lt;br /&gt;
* Le nombre de points décrivant le contour du trou&lt;br /&gt;
* Les coordonnées relatives entre chaque point du contour du trou&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Format GRASS :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;14 lignes d&#039;en-tête comprenant des renseignements divers&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; A 69&amp;lt;br /&amp;gt; 2462669.95 911561.09&amp;lt;br /&amp;gt; 2462669.96 911561.09&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt; Soit en clair :&lt;br /&gt;
&lt;br /&gt;
* 11 lignes inutiles pour nous, recollées directement d&#039;un header.&lt;br /&gt;
* A 25 : pour dire que c&#039;est une surface (area) et que son contour comporte 25 points&lt;br /&gt;
* Les coordonnées absolues y et x des points du contour de la surface&lt;br /&gt;
* Les mêmes renseignements pour les trous&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Les bouts intéressants du script&#039;&#039;&#039; &amp;lt;tt&amp;gt; BEGIN {&amp;lt;br /&amp;gt; melange = &amp;quot;v.patch input=&amp;quot;&amp;lt;br /&amp;gt; exited = 0&amp;lt;br /&amp;gt; getline h1 &amp;lt; &amp;quot;header&amp;quot;&amp;lt;br /&amp;gt; getline h2 &amp;lt; &amp;quot;header&amp;quot;&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; !/\/\// {&amp;lt;br /&amp;gt; print h1 &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1&amp;lt;br /&amp;gt; print h2 &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; melange = melange $1 &amp;quot;.awkImport,&amp;quot;&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; beginObj = 5&amp;lt;br /&amp;gt; if ( (beginObj + 2 + $(beginObj+2) * 2) &amp;lt; NF) {&amp;lt;br /&amp;gt; nbTrou = $((beginObj+3) + $(beginObj+2) * 2)&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; else {&amp;lt;br /&amp;gt; nbTrou = 0&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; for ( i=0 ; i &amp;lt; nbTrou+1 ; i++) {&amp;lt;br /&amp;gt; actualx = $beginObj&amp;lt;br /&amp;gt; actualy = $(beginObj+1)&amp;lt;br /&amp;gt; print &amp;quot;A &amp;quot; ($(beginObj+2)+2) &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1&amp;lt;br /&amp;gt; print &amp;quot; &amp;quot; actualy &amp;quot; &amp;quot; actualx &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; for ( j=(beginObj+3) ; j&amp;lt;(beginObj+3)+$(beginObj+2)*2-1 ; j++ ) {&amp;lt;br /&amp;gt; actualx += $j&amp;lt;br /&amp;gt; actualy += $(++j)&amp;lt;br /&amp;gt; print &amp;quot; &amp;quot; actualy &amp;quot; &amp;quot; actualx &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; print &amp;quot; &amp;quot; $(beginObj+1) &amp;quot; &amp;quot; $beginObj &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; fflush (ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1)&amp;lt;br /&amp;gt; close (ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_ascii/&amp;quot; $1)&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; if ( system(&amp;quot;v.support map=&amp;quot; $1 &amp;quot;.awkImport option=build -s threshold=&amp;quot; thresh &amp;quot; &amp;gt;/dev/null&amp;quot;)!=0 )&amp;lt;br /&amp;gt; exit (1)&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; END {&amp;lt;br /&amp;gt; print &amp;quot;Patching all files into composite.awkImport&amp;quot;&amp;lt;br /&amp;gt; if ( system (melange &amp;quot; output=composite.awkImport&amp;quot; ) != 0 )&amp;lt;br /&amp;gt; exit (1)&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; for (i=1;i&amp;lt;=FNR;i++) {&amp;lt;br /&amp;gt; getline &amp;lt; ARGV[1]&amp;lt;br /&amp;gt; print i &amp;quot;:&amp;quot; $4 &amp;gt; ENVIRON[&amp;quot;LOCATION&amp;quot;] &amp;quot;/dig_cats/&amp;quot; mapName&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; system (effaceTempos &amp;quot; &amp;gt; /dev/null&amp;quot;)&amp;lt;br /&amp;gt; fflush ()&amp;lt;br /&amp;gt; ...&amp;lt;br /&amp;gt; }&amp;lt;br /&amp;gt; &amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons ensemble analyser les morceaux intéressants de ce script.&lt;br /&gt;
&lt;br /&gt;
Tout d&#039;abord, je définis quelques variables dans la section BEGIN, qui restent accessibles jusqu&#039;à la fin de l&#039;exécution. Ensuite j&#039;affecte des valeurs aux variables h1 et h2 en lisant les lignes dans un fichier du répertoire courant nommé &amp;lt;code&amp;gt;header&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Pour chaque objet (tout ce qui ne commence pas par //), j&#039;insère un entête GRASS, composé des variables h1, h2, etc... que je range dans un fichier avec le symbole de redirection &amp;lt;code&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; dont le chemin est la concaténation de la variable d&#039;environnement LOCATION (&amp;lt;code&amp;gt;ENVIRON[&amp;quot;LOCATION&amp;quot;]&amp;lt;/code&amp;gt;), de la chaîne &amp;lt;code&amp;gt;&amp;quot;/dig_ascii/&amp;quot;&amp;lt;/code&amp;gt; et de la première colonne de la ligne que je suis en train de lire (&amp;lt;code&amp;gt;$1&amp;lt;/code&amp;gt;).&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;ajoute à la variable &amp;lt;code&amp;gt;melange&amp;lt;/code&amp;gt; une chaine constituée de ma variable &amp;lt;code&amp;gt;$1&amp;lt;/code&amp;gt; et de la chaine &amp;lt;code&amp;gt;&amp;quot;.awkImport&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je dis que les coordonnées de l&#039;objet commencent à la colonne 5. Ceci me dit (voir explications du format GC ci-dessus) que si il y a des trous, c&#039;est à dire si la somme du double du nombre de points intermédiaires donné en colonne 7 (&amp;lt;code&amp;gt;$(beginObj+2)&amp;lt;/code&amp;gt; équivaut à &amp;lt;code&amp;gt;$7&amp;lt;/code&amp;gt; car &amp;lt;code&amp;gt;beginObj&amp;lt;/code&amp;gt; vaut 5)+ les cinq colonnes de départ + 2 pour les 2 premières coordonnées absolues est inférieur au nombre total de colonnes de la ligne contenu dans la variable &amp;lt;code&amp;gt;NF&amp;lt;/code&amp;gt;, alors leur nombre me serra donné à la colonne suivant ce nombre de colonnes précalculé, d&#039;où le &amp;lt;code&amp;gt;nbTrous = $((beginObj+3) + $(beginObj+2) * 2)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ensuite la reconstitution des coordonnées absolues et l&#039;inscription dans le fichier utilisé plus haut donne l&#039;occasion de voir la syntaxe des boucles &amp;lt;code&amp;gt;for&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On flushe le buffer du fichier et on le ferme. Au début j&#039;avais oublié, alors, je me suis retrouvé avec BEAUCOUP TROP de fichiers ouverts. Vous me direz, le fichier je l&#039;ai pas ouvert. Bé, oui, c&#039;est le côté expérimentation hasardeuse qui m&#039;a fait comprendre. M&#039;enfin, vous pourrez pas dire : &amp;quot;euh, ben, je comprends pas pourquoi mon linux me dit que le script il doit s&#039;arrêter à cause que j&#039;ai un problème de ressources&amp;quot;.&amp;lt;br /&amp;gt; Ceci dit, je peux me tromper aussi. Si j&#039;ai tort envoyez moi un mail.&lt;br /&gt;
&lt;br /&gt;
La ligne suivante nous donne un exemple d&#039;utilisation de la commande system, avec récupération du code de retour et aussi de la commande exit. RAS.&lt;br /&gt;
&lt;br /&gt;
La suite montre l&#039;utilisation de variables telles que FNR, ARGV ainsi que des appels à la fonction système avec redirection et l&#039;utilisation des variables déclarées dans le begin et que l&#039;on a fait évoluer au cours du script.&lt;br /&gt;
&lt;br /&gt;
== Le mot de la fin, enfin ;-) ==&lt;br /&gt;
&lt;br /&gt;
Voilà, j&#039;espère vous avoir fait comprendre ce qu&#039;était awk et à quoi il servait. Bien sûr on peut faire la même chose en Perl, PHP, C, Java. Je sais. Mais utiliser awk plutôt que Perl quand il est adapté c&#039;est un peu comme aller dans un petit hôtel/restaurant pittoresque plutôt que d&#039;aller au Club Med. En plus, awk est très léger et peut être un allié puissant dans les systèmes embarqués.&lt;br /&gt;
&lt;br /&gt;
Nota : Je vous ai généré un pdf du manuel de awk accessible [awk.pdf ici] (64ko). Petit rappel en passant : la manipulation pour générer des pdf à partir des pages de manuel se trouve sur [http://lea-linux.org Léa] section [../trucs Trucs et astuces], rubrique [/trucs/sommaire.php3?cat=6 Shell].&lt;br /&gt;
&lt;br /&gt;
a+&amp;lt;br /&amp;gt; Xavier&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;merci&amp;quot;&amp;gt;Cette page est issue de la documentation &#039;pré-wiki&#039; de Léa a été convertie avec HTML::WikiConverter. Elle fut créée par Xavier GARREAU le 18/04/2001.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Copyright =&lt;br /&gt;
Copyright &amp;amp;copy; 18/04/2001, Xavier GARREAU&lt;br /&gt;
{{CC-BY-NC-SA}}&lt;/div&gt;</summary>
		<author><name>BernardTV</name></author>
	</entry>
	<entry>
		<id>https://lea-linux.org/docs/index.php?title=Utiliser_groff&amp;diff=11131</id>
		<title>Utiliser groff</title>
		<link rel="alternate" type="text/html" href="https://lea-linux.org/docs/index.php?title=Utiliser_groff&amp;diff=11131"/>
		<updated>2005-12-16T11:27:18Z</updated>

		<summary type="html">&lt;p&gt;BernardTV : /* Quelles sont ses origines ? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Comme Monsieur Jourdain fait de la prose, la plupart des nouveaux utilisateurs et utilisatrices de notre OS libre préféré utilisent un puissant outil de formatage et génération de documents. Cet outil a tendance à se faire oublier, tellement il est discret malgré sa participation vitale au quotidien de tout utilisateur ou utilisatrice, et cela concerne même les plus chevronné(e)s. Cet outil, c&#039;est &amp;lt;code&amp;gt;groff&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Que peut-on faire avec groff ? ==&lt;br /&gt;
&lt;br /&gt;
La commande &#039;&#039;&#039;groff&#039;&#039;&#039; permet à partir d&#039;une même source de :&lt;br /&gt;
&lt;br /&gt;
* générer des documents mis en page : livre, lettre, documentation, rapport...etc.&lt;br /&gt;
* créer des images de ces documents en format : postscript, man (Latin 1 formatés), html, dvi, Textes (Latin1 formatés)...&lt;br /&gt;
&lt;br /&gt;
== Quelles sont ses origines ? ==&lt;br /&gt;
&lt;br /&gt;
Au départ, cet environnement de formatage de documents appelé &#039;&#039;&#039;troff&#039;&#039;&#039; a été développé en assembleur par Joe Ossanna vers 1973, pour piloter une imprimante graphique (Graphic System CAT Typesetter) branchée sur un bon vieux PDP-11. Il fut porté en C vers 1975, mais malheureusement, Joe Ossanna décède en 1977.&lt;br /&gt;
&lt;br /&gt;
C&#039;est le célèbre Brian Kernighan qui reprend le flambeau en 1979 et modifie &#039;&#039;&#039;troff&#039;&#039;&#039; afin de le rendre compatible avec d&#039;autres formats de sortie. de 1979 à 1989, les sources de &#039;&#039;&#039;troff&#039;&#039;&#039; ont été modestement retouchées de manière à laisser la quasi totalité du code intacte en mémoire de Joe Ossanna. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;groff&#039;&#039;&#039; est donc en quelque sorte une oeuvre postume  trouvant ses d&#039;origines à quelques pas de l&#039;OS &#039;&#039;&#039;UNIX&#039;&#039;&#039;. Cet utilitaire extrèmement efficace est aujourd&#039;hui porté sur les systèmes d&#039;exploitations les plus novateurs tels que &#039;&#039;&#039;plan 9&#039;&#039;&#039;, &#039;&#039;&#039;inferno&#039;&#039;&#039; ou encore &#039;&#039;&#039;Amoeba&#039;&#039;&#039;.&lt;br /&gt;
Dans ces différents portages, il se fait parfois appeler &#039;&#039;&#039;roff&#039;&#039;&#039;, &#039;&#039;&#039;nroff&#039;&#039;&#039;, &#039;&#039;&#039;troff&#039;&#039;&#039;, mais est toujours présent sur tout système de philosophie UNIX.&lt;br /&gt;
&lt;br /&gt;
Il présente parfois de légères différences selon les spécificités des plateformes afin d&#039;en tirer le meilleur parti, mais semble toujours compatible car les développeurs d&#039;environnement ont prévu des équivalences afin de toujours pourvoir générer des documents propores.&lt;br /&gt;
Même &#039;&#039;&#039;MINIX&#039;&#039;&#039; célèbre petit OS didactique développé par Andrew Tenenbaum (MINIX mais il fait le maximum...) dispose de cette commande !&lt;br /&gt;
&lt;br /&gt;
== Les forces et faiblesses de groff ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Forces :&#039;&#039;&#039;&lt;br /&gt;
*Très rapide à assimiler comparé a son &#039;grand frêre&#039; &#039;&#039;&#039;L&amp;lt;sup&amp;gt;A&amp;lt;/sup&amp;gt;T&amp;lt;sub&amp;gt;E&amp;lt;/sub&amp;gt;X&#039;&#039;&#039;.&lt;br /&gt;
*Grande robustesse et génération toujours fidèle aux attentes de l&#039;utilisateur.&lt;br /&gt;
*Très léger, il permet un traitement rapide des informations même sur des petites configurations ne *disposant pas d&#039;une interface X-Windows.&lt;br /&gt;
*Personnalisable&lt;br /&gt;
&#039;&#039;&#039;Faiblesses :&#039;&#039;&#039;(il en faut bien pour rester objectif)&lt;br /&gt;
*Son langage macro est un peu rébarbatif (mais après un petit effort, il devient vite familier).&lt;br /&gt;
*Un peut plus rigide que &#039;&#039;&#039;L&amp;lt;sup&amp;gt;A&amp;lt;/sup&amp;gt;T&amp;lt;sub&amp;gt;E&amp;lt;/sub&amp;gt;X&#039;&#039;&#039; losque l&#039;on souhaite personnaliser un document.&lt;br /&gt;
*Peu de documentations sont disponibles étant donné son grand age.&lt;br /&gt;
&lt;br /&gt;
== Un exemple ! un exemple ! un exemple... ==&lt;br /&gt;
&lt;br /&gt;
Comme mentionné précédemment, &#039;&#039;&#039;groff&#039;&#039;&#039; est présent sur votre ordinateur, et vous disposez déjà d&#039;exemples sources ! Il vous suffit par exemple d&#039;ouvrir un fichier de type man, pour cela, il vous suffit de choisir un petit exemple parmis les centaines de documentations man.&lt;br /&gt;
&lt;br /&gt;
=== Comment procéder ? ===&lt;br /&gt;
# Trouver l&#039;emplacement des sources des fichiers de documentations du système.&lt;br /&gt;
# Copier une commande dans votre répertoire de travail habituel.&lt;br /&gt;
# Décompresser le fichier.&lt;br /&gt;
# Ouvrir le fichier dans votre édteur de texte habituel.&lt;br /&gt;
# Contempler...&lt;br /&gt;
&lt;br /&gt;
==== En pratique ====&lt;br /&gt;
Bien que je sois persuadé que la plupart d&#039;entre-vous ont directement &amp;quot;switché&amp;quot; en mode console et sont déjà en train de tripatouiller un fichier juste pour voir, je vous donne ici les grandes directions qui vous permettrons de trouver ces fichiers.&lt;br /&gt;
==== Trouver les fichiers sources man ====&lt;br /&gt;
Vous pouvez les chercher à la main, en changeant de répertoire. Généralement, on les trouve dans les parages de &amp;lt;tt&amp;gt;/usr/man&amp;lt;/tt&amp;gt; ou encore &amp;lt;tt&amp;gt;/usr/share/man&amp;lt;/tt&amp;gt; ou encore &amp;lt;tt&amp;gt;/usr/local/man&amp;lt;/tt&amp;gt; et bien d&#039;autres endroits. &lt;br /&gt;
&lt;br /&gt;
Choisissez un répertoire parmi &#039;&#039;man1&#039;&#039;,&#039;&#039;man2&#039;&#039;,...,&#039;&#039;mann&#039;&#039; situés dans le répertoire &#039;&#039;/.../man/&#039;&#039; ou &#039;&#039;/.../man/fr/&#039;&#039;.&lt;br /&gt;
&amp;lt;code multi&amp;gt;&lt;br /&gt;
[mujma@localhost]#ls -l /usr/share/man&lt;br /&gt;
total 300&lt;br /&gt;
drwxr-xr-x   4 root root   4096 aoû 17 20:12 bg&lt;br /&gt;
drwxr-xr-x   2 root root   4096 aoû 17 20:26 cat1&lt;br /&gt;
drwxr-xr-x   2 root root   4096 aoû 17 20:26 cat5&lt;br /&gt;
drwxr-xr-x   5 root root   4096 aoû 17 20:12 cs&lt;br /&gt;
...&lt;br /&gt;
drwxr-xr-x  11 root man    4096 aoû 17 20:16 fr&lt;br /&gt;
...&lt;br /&gt;
drwxr-xr-x   2 root root  40960 nov 16 22:51 man1&lt;br /&gt;
drwxr-xr-x   2 root root   4096 jan  5  2004 man2&lt;br /&gt;
drwxr-xr-x   2 root root 114688 nov  8 08:47 man3&lt;br /&gt;
drwxr-xr-x   2 root root   4096 aoû 18 14:23 man4&lt;br /&gt;
drwxr-xr-x   2 root root   8192 nov 16 22:51 man5&lt;br /&gt;
drwxr-xr-x   2 root root   4096 aoû 17 20:20 man6&lt;br /&gt;
drwxr-xr-x   2 root root   4096 oct 20 18:20 man7&lt;br /&gt;
drwxr-xr-x   2 root root  12288 nov  2 15:07 man8&lt;br /&gt;
drwxr-xr-x   2 root root   4096 jan  5  2004 man9&lt;br /&gt;
drwxr-xr-x   2 root root   8192 aoû 17 20:29 mann&lt;br /&gt;
drwxr-xr-x   5 root root   4096 aoû 17 20:12 nl&lt;br /&gt;
...&lt;br /&gt;
drwxr-xr-x   4 root root   4096 aoû 17 20:12 sl&lt;br /&gt;
drwxr-xr-x   3 root root   4096 aoû 17 20:10 uk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En listant le répertoire désiré on obtient donc la liste des commades :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code multi&amp;gt;&lt;br /&gt;
[mujma@localhost]#ls -l /usr/share/man/fr/man1/&lt;br /&gt;
total 4036&lt;br /&gt;
-rw-r--r--  1 root man    962 jan 31  1999 3ds2m.1.bz2&lt;br /&gt;
-rw-r--r--  1 root man    967 jul 03  1999 3dsdump.1.bz2&lt;br /&gt;
-rw-r--r--  1 root man   1641 jun 13  2001 9wm.1.bz2&lt;br /&gt;
...&lt;br /&gt;
-rw-r--r--  1 root man   6531 aoû 10  2003 ls.1.bz2 &amp;lt;-------- On va copier ce fichier dans le répertoire $HOME&lt;br /&gt;
...&lt;br /&gt;
-rw-r--r--  1 root man   2251 apr 08  1989 zmore.1.bz2&lt;br /&gt;
-rw-r--r--  1 root man    751 apr 08  1989 znew.1.bz2&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin on peut copier le fichier et le décompresser :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code multi&amp;gt;&lt;br /&gt;
[mujma@localhost]#cp /usr/share/man/fr/man1/ls.1.bz2 $HOME&lt;br /&gt;
[mujma@localhost]#bunzip2 ls.1.bz2&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
==== Ouvrir un exemple ====&lt;br /&gt;
Enfin, si on ouvre ce fichier dans un éditeur de texte on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code multi&amp;gt;&lt;br /&gt;
.\&amp;quot; Traduction 19/12/1996 par Christophe Blaess (ccb@club-internet.fr)&lt;br /&gt;
.\&amp;quot; màj 04/01/1999 - LDP man-pages 1.22&lt;br /&gt;
.\&amp;quot; màj 03/01/2000&lt;br /&gt;
.\&amp;quot; màj 26/06/2000 - LDP man-pages 1.30&lt;br /&gt;
.\&amp;quot; màj 30/05/2001 - LDP man-pages 1.36&lt;br /&gt;
.\&amp;quot; màj 22/10/2002 - LDP man-pages 1.53&lt;br /&gt;
.\&amp;quot; MàJ 25/07/2003 LDP-1.56&lt;br /&gt;
.TH LS 1L &amp;quot;25 juillet 2003&amp;quot; LDP &amp;quot;Manuel de l&#039;utilisateur Linux&amp;quot;&lt;br /&gt;
.SH NOM&lt;br /&gt;
ls, dir, vdir \- Afficher le contenu d&#039;un répertoire.&lt;br /&gt;
.SH SYNOPSIS&lt;br /&gt;
.BI &amp;quot;ls [&amp;quot; options &amp;quot;] [&amp;quot; fichier... ]&lt;br /&gt;
.br&lt;br /&gt;
.BI &amp;quot;dir [&amp;quot; fichier... ]&lt;br /&gt;
.br&lt;br /&gt;
.BI &amp;quot;vdir [&amp;quot; fichier... ]&lt;br /&gt;
.sp&lt;br /&gt;
Options POSIX :&lt;br /&gt;
.BI &amp;quot;[\-CFRacdilqrtu1] [\-\-]&amp;quot;&lt;br /&gt;
.sp&lt;br /&gt;
Options GNU (forme courte) :&lt;br /&gt;
.B [\-1abcdfgiklmnopqrstuvwxABCDFGHLNQRSUX]&lt;br /&gt;
.BI &amp;quot;[\-w &amp;quot; cols ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  ... &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cette page documente la version de&lt;br /&gt;
.B ls&lt;br /&gt;
du paquetage fileutils-4.0. D&#039;autres versions peuvent diverger légèrement.&lt;br /&gt;
 &lt;br /&gt;
.SH TRADUCTION&lt;br /&gt;
Christophe Blaess, 1996-2003.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Faire un petit tour de groff ====&lt;br /&gt;
Avant de réellement comprendre la signification des codes étranges et barbares parfois situés en début de ligne, je vous invite maintenant à quitter votre éditeur pour rejoindre votre console.&lt;br /&gt;
&lt;br /&gt;
Nous allons maintenant faire quelques manipulations pratique sur le fichier ls.1 que nous avons recopier tout dernièrement dans notre répertoire de travail habituel.&lt;br /&gt;
&lt;br /&gt;
Tapez la commande suivante :&lt;br /&gt;
&amp;lt;code&amp;gt;[mujma@localhost]#groff -Tps -man ls.1 &amp;gt; ls.1.ps&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si groff est correctement installé (et il y a 99,9% de chances qu&#039;il le soit), vous devriez voir apparaître le fichier &amp;lt;tt&amp;gt;ls.1.ps&amp;lt;/tt&amp;gt; dans le répertoire courant.&lt;br /&gt;
&lt;br /&gt;
Vous pouvez le visualiser avec n&#039;importe quel afficheur postscript.&lt;br /&gt;
&lt;br /&gt;
Maintenant nous allons faire encore plus fort ! Pour cela tapez la commande :&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
[mujma@localhost]#groff -Thtml -man ls.1 &amp;gt; ls.1.html&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
De manière identique à la commande précédente, vous venez de générer un fichier html. Ouvrez-le vite... Oui, c&#039;est bien la documentation au format html.&lt;br /&gt;
Vous pouvez procéder ainsi avec toutes les pages de manuel linux !&lt;br /&gt;
En fait, groff est un préprocesseur. Il permet de générer les formats suivants à partir d&#039;une seule source :&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;dvi&#039;&#039;&#039; :  Pour ceux qui connaissent, c&#039;est le format TeX/LaTeX DVI.&lt;br /&gt;
; &#039;&#039;&#039;html&#039;&#039;&#039; : c&#039;est le format bien connu dont le nom signifie Hyper Text Markup Language et non, contrairement à ce que certains sous entendent parfois Hautes Technologies Mais Limitées.&lt;br /&gt;
; &#039;&#039;&#039;lbp&#039;&#039;&#039; : Format CAPSL pour les imprimantes laser Canon de type lbp-4 ou lpb-8.&lt;br /&gt;
; &#039;&#039;&#039;lj4&#039;&#039;&#039; : Format PCL5 pour imprimantes HP et compatibles.&lt;br /&gt;
; &#039;&#039;&#039;ps&#039;&#039;&#039; : Du vrai postscript bien de chez nous !&lt;br /&gt;
; &#039;&#039;&#039;ascii&#039;&#039;&#039; : C&#039;est le format ASCII 7-Bits, je le testerai peut-être cet hiver s&#039;il y a de la neige.&lt;br /&gt;
; &#039;&#039;&#039;cp1047&#039;&#039;&#039; : Historiquement destiné à certains serveurs internet et autres mainframes qui n&#039;ont toujours pas étés concurrencés par un certain Bill G. qui impose au monde le cp1250 dans les clicodrômes vitrés depuis la version nonante cinq , mais aussi langage natif de l&#039;imprimante qui vous sert peut-être aujourd&#039;hui de bac à fleurs, ce format implémente le jeux de caractères latin-1 en EBCDIC.&lt;br /&gt;
; &#039;&#039;&#039;latin1&#039;&#039;&#039; : C&#039;est le jeu de caractères ISO 8859-1 utilisé par exemple pour afficher des symboles mystérieux appartenant à l&#039;obscur langage qu&#039;étaient le François et le Français. On notera au passage qu&#039;il offre aussi l&#039;avantage d&#039;afficher des messages en &amp;quot;verlan&amp;quot; et en &amp;quot;nique ta m...&amp;quot; ou encore &amp;quot;nique ta r...&amp;quot; dialectes évolués de notre époque concurrençant le &amp;quot;slang&amp;quot; parlé dans les prisons anglo-saxonnes.&lt;br /&gt;
; &#039;&#039;&#039;utf8&#039;&#039;&#039; : C&#039;est le jeu de caractères Unicode UTF-8, similaire à celui du bios de votre machine.&lt;br /&gt;
&lt;br /&gt;
== groff et ses environnements ==&lt;br /&gt;
&lt;br /&gt;
Si l&#039;on se réfère à l&#039;invocation de &#039;&#039;&#039;groff&#039;&#039;&#039; dans l&#039;exemple précédent, groff est invoqué avec 3 paramètres en ligne de commande.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;groff -Thtml -m man ls.1 &amp;gt; ls.1.html&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
de manière plus générale on peut invoquer groff de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;groff -T&#039;&amp;lt;format_sortie&amp;gt;&#039; -m &#039;&amp;lt;format_entrée&amp;gt;&#039; &amp;gt; ls.1.html&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&amp;lt;format_sortie&amp;gt;&#039; correspond aux formats de sorties évoqués précédemment.&lt;br /&gt;
&lt;br /&gt;
&#039;&amp;lt;format_entrée&amp;gt;&#039; correspond au format utilisé pour écrire le source.&lt;br /&gt;
&lt;br /&gt;
Pour groff un format de sortie ou un format d&#039;entrée n&#039;est ni plus ni moins qu&#039;un ensemble de macros correspondant à des environnements.&lt;br /&gt;
&lt;br /&gt;
On trouve généralement les environnements (ou format d&#039;entrée) suivants avec le paquet groff :&lt;br /&gt;
&lt;br /&gt;
Les environnement macro dédiés au système de documentation :&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;man&#039;&#039;&#039; : format traditionnel des pages de manuel.&lt;br /&gt;
; &#039;&#039;&#039;mdoc&#039;&#039;&#039; : format BSD des pages de manuel.&lt;br /&gt;
; &#039;&#039;&#039;mandoc&#039;&#039;&#039; : cet environnement encapsule man et mdoc et permet de reconnaître le format du fichier d&#039;origine automatiquement.&lt;br /&gt;
&lt;br /&gt;
Pour des documents plus courants :&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;me&#039;&#039;&#039;, &#039;&#039;&#039;mm&#039;&#039;&#039; et &#039;&#039;&#039;ms&#039;&#039;&#039; : des environnements de génération de documents plus classiques (livres, rapports...).&lt;br /&gt;
&lt;br /&gt;
Pour générer des pages Web :&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;www&#039;&#039;&#039; : pour générer des documents &#039;HTML&#039;.&lt;br /&gt;
&lt;br /&gt;
== Où peut-on trouver des informations sur groff ==&lt;br /&gt;
&lt;br /&gt;
Les sites suivants vous apporterons diverses ressources pour &#039;&#039;&#039;groff&#039;&#039;&#039;:&lt;br /&gt;
* http://www.gnu.org/software/groff/groff.html&lt;br /&gt;
* http://www.troff.org/&lt;br /&gt;
* http://www.kohala.com/start/troff/troff.html&lt;br /&gt;
&lt;br /&gt;
{{Copy|2005|Marc UJMA|CC-BY-SA}}&lt;/div&gt;</summary>
		<author><name>BernardTV</name></author>
	</entry>
	<entry>
		<id>https://lea-linux.org/docs/index.php?title=Utiliser_groff&amp;diff=11130</id>
		<title>Utiliser groff</title>
		<link rel="alternate" type="text/html" href="https://lea-linux.org/docs/index.php?title=Utiliser_groff&amp;diff=11130"/>
		<updated>2005-12-16T11:25:08Z</updated>

		<summary type="html">&lt;p&gt;BernardTV : /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Comme Monsieur Jourdain fait de la prose, la plupart des nouveaux utilisateurs et utilisatrices de notre OS libre préféré utilisent un puissant outil de formatage et génération de documents. Cet outil a tendance à se faire oublier, tellement il est discret malgré sa participation vitale au quotidien de tout utilisateur ou utilisatrice, et cela concerne même les plus chevronné(e)s. Cet outil, c&#039;est &amp;lt;code&amp;gt;groff&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Que peut-on faire avec groff ? ==&lt;br /&gt;
&lt;br /&gt;
La commande &#039;&#039;&#039;groff&#039;&#039;&#039; permet à partir d&#039;une même source de :&lt;br /&gt;
&lt;br /&gt;
* générer des documents mis en page : livre, lettre, documentation, rapport...etc.&lt;br /&gt;
* créer des images de ces documents en format : postscript, man (Latin 1 formatés), html, dvi, Textes (Latin1 formatés)...&lt;br /&gt;
&lt;br /&gt;
== Quelles sont ses origines ? ==&lt;br /&gt;
&lt;br /&gt;
Au départ, cet environnement de formatage de documents appelé &#039;&#039;&#039;troff&#039;&#039;&#039; a été développé en assembleur par Joe Ossanna vers 1973, pour piloter une imprimante graphique (Graphic System CAT Typesetter) branchée sur un bon vieux PDP-11. Il fut porté en C vers 1975, mais malheureusement, Joe Ossanna décède en 1977.&lt;br /&gt;
&lt;br /&gt;
C&#039;est le célèbre Brian Kernighan qui reprend le flambeau en 1979 et modifie &#039;&#039;&#039;troff&#039;&#039;&#039; afin de le rendre compatible avec d&#039;autres formats de sortie. de 1979 à 1989, les sources de &#039;&#039;&#039;troff&#039;&#039;&#039; ont été modestement retouchées de manière à laisser la quasie totalité du code intacte en mémoire de Joe Ossanna. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;groff&#039;&#039;&#039; est donc en quelque sorte une oeuvre postume  trouvant ses d&#039;origines à quelques pas de l&#039;OS &#039;&#039;&#039;UNIX&#039;&#039;&#039;. Cet utilitaire extrèmement efficace est aujourd&#039;hui porté sur les systèmes d&#039;exploitations les plus novateurs tels que &#039;&#039;&#039;plan 9&#039;&#039;&#039;, &#039;&#039;&#039;inferno&#039;&#039;&#039; ou encore &#039;&#039;&#039;Amoeba&#039;&#039;&#039;.&lt;br /&gt;
Dans ces différents portages, il se fait parfois appeler &#039;&#039;&#039;roff&#039;&#039;&#039;, &#039;&#039;&#039;nroff&#039;&#039;&#039;, &#039;&#039;&#039;troff&#039;&#039;&#039;, mais est toujours présent sur tout système de philosophie UNIX.&lt;br /&gt;
&lt;br /&gt;
Il présente parfois de légères différences selon les spécificités des plateformes afin d&#039;en tirer le meilleur parti, mais semble toujours compatible car les développeurs d&#039;environnement ont prévu des équivalences afin de toujours pourvoir générer des documents propores.&lt;br /&gt;
Même &#039;&#039;&#039;MINIX&#039;&#039;&#039; célèbre petit OS didactique développé par Andrew Tenenbaum (MINIX mais il fait le maximum...) dispose de cette commande !&lt;br /&gt;
&lt;br /&gt;
== Les forces et faiblesses de groff ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Forces :&#039;&#039;&#039;&lt;br /&gt;
*Très rapide à assimiler comparé a son &#039;grand frêre&#039; &#039;&#039;&#039;L&amp;lt;sup&amp;gt;A&amp;lt;/sup&amp;gt;T&amp;lt;sub&amp;gt;E&amp;lt;/sub&amp;gt;X&#039;&#039;&#039;.&lt;br /&gt;
*Grande robustesse et génération toujours fidèle aux attentes de l&#039;utilisateur.&lt;br /&gt;
*Très léger, il permet un traitement rapide des informations même sur des petites configurations ne *disposant pas d&#039;une interface X-Windows.&lt;br /&gt;
*Personnalisable&lt;br /&gt;
&#039;&#039;&#039;Faiblesses :&#039;&#039;&#039;(il en faut bien pour rester objectif)&lt;br /&gt;
*Son langage macro est un peu rébarbatif (mais après un petit effort, il devient vite familier).&lt;br /&gt;
*Un peut plus rigide que &#039;&#039;&#039;L&amp;lt;sup&amp;gt;A&amp;lt;/sup&amp;gt;T&amp;lt;sub&amp;gt;E&amp;lt;/sub&amp;gt;X&#039;&#039;&#039; losque l&#039;on souhaite personnaliser un document.&lt;br /&gt;
*Peu de documentations sont disponibles étant donné son grand age.&lt;br /&gt;
&lt;br /&gt;
== Un exemple ! un exemple ! un exemple... ==&lt;br /&gt;
&lt;br /&gt;
Comme mentionné précédemment, &#039;&#039;&#039;groff&#039;&#039;&#039; est présent sur votre ordinateur, et vous disposez déjà d&#039;exemples sources ! Il vous suffit par exemple d&#039;ouvrir un fichier de type man, pour cela, il vous suffit de choisir un petit exemple parmis les centaines de documentations man.&lt;br /&gt;
&lt;br /&gt;
=== Comment procéder ? ===&lt;br /&gt;
# Trouver l&#039;emplacement des sources des fichiers de documentations du système.&lt;br /&gt;
# Copier une commande dans votre répertoire de travail habituel.&lt;br /&gt;
# Décompresser le fichier.&lt;br /&gt;
# Ouvrir le fichier dans votre édteur de texte habituel.&lt;br /&gt;
# Contempler...&lt;br /&gt;
&lt;br /&gt;
==== En pratique ====&lt;br /&gt;
Bien que je sois persuadé que la plupart d&#039;entre-vous ont directement &amp;quot;switché&amp;quot; en mode console et sont déjà en train de tripatouiller un fichier juste pour voir, je vous donne ici les grandes directions qui vous permettrons de trouver ces fichiers.&lt;br /&gt;
==== Trouver les fichiers sources man ====&lt;br /&gt;
Vous pouvez les chercher à la main, en changeant de répertoire. Généralement, on les trouve dans les parages de &amp;lt;tt&amp;gt;/usr/man&amp;lt;/tt&amp;gt; ou encore &amp;lt;tt&amp;gt;/usr/share/man&amp;lt;/tt&amp;gt; ou encore &amp;lt;tt&amp;gt;/usr/local/man&amp;lt;/tt&amp;gt; et bien d&#039;autres endroits. &lt;br /&gt;
&lt;br /&gt;
Choisissez un répertoire parmi &#039;&#039;man1&#039;&#039;,&#039;&#039;man2&#039;&#039;,...,&#039;&#039;mann&#039;&#039; situés dans le répertoire &#039;&#039;/.../man/&#039;&#039; ou &#039;&#039;/.../man/fr/&#039;&#039;.&lt;br /&gt;
&amp;lt;code multi&amp;gt;&lt;br /&gt;
[mujma@localhost]#ls -l /usr/share/man&lt;br /&gt;
total 300&lt;br /&gt;
drwxr-xr-x   4 root root   4096 aoû 17 20:12 bg&lt;br /&gt;
drwxr-xr-x   2 root root   4096 aoû 17 20:26 cat1&lt;br /&gt;
drwxr-xr-x   2 root root   4096 aoû 17 20:26 cat5&lt;br /&gt;
drwxr-xr-x   5 root root   4096 aoû 17 20:12 cs&lt;br /&gt;
...&lt;br /&gt;
drwxr-xr-x  11 root man    4096 aoû 17 20:16 fr&lt;br /&gt;
...&lt;br /&gt;
drwxr-xr-x   2 root root  40960 nov 16 22:51 man1&lt;br /&gt;
drwxr-xr-x   2 root root   4096 jan  5  2004 man2&lt;br /&gt;
drwxr-xr-x   2 root root 114688 nov  8 08:47 man3&lt;br /&gt;
drwxr-xr-x   2 root root   4096 aoû 18 14:23 man4&lt;br /&gt;
drwxr-xr-x   2 root root   8192 nov 16 22:51 man5&lt;br /&gt;
drwxr-xr-x   2 root root   4096 aoû 17 20:20 man6&lt;br /&gt;
drwxr-xr-x   2 root root   4096 oct 20 18:20 man7&lt;br /&gt;
drwxr-xr-x   2 root root  12288 nov  2 15:07 man8&lt;br /&gt;
drwxr-xr-x   2 root root   4096 jan  5  2004 man9&lt;br /&gt;
drwxr-xr-x   2 root root   8192 aoû 17 20:29 mann&lt;br /&gt;
drwxr-xr-x   5 root root   4096 aoû 17 20:12 nl&lt;br /&gt;
...&lt;br /&gt;
drwxr-xr-x   4 root root   4096 aoû 17 20:12 sl&lt;br /&gt;
drwxr-xr-x   3 root root   4096 aoû 17 20:10 uk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En listant le répertoire désiré on obtient donc la liste des commades :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code multi&amp;gt;&lt;br /&gt;
[mujma@localhost]#ls -l /usr/share/man/fr/man1/&lt;br /&gt;
total 4036&lt;br /&gt;
-rw-r--r--  1 root man    962 jan 31  1999 3ds2m.1.bz2&lt;br /&gt;
-rw-r--r--  1 root man    967 jul 03  1999 3dsdump.1.bz2&lt;br /&gt;
-rw-r--r--  1 root man   1641 jun 13  2001 9wm.1.bz2&lt;br /&gt;
...&lt;br /&gt;
-rw-r--r--  1 root man   6531 aoû 10  2003 ls.1.bz2 &amp;lt;-------- On va copier ce fichier dans le répertoire $HOME&lt;br /&gt;
...&lt;br /&gt;
-rw-r--r--  1 root man   2251 apr 08  1989 zmore.1.bz2&lt;br /&gt;
-rw-r--r--  1 root man    751 apr 08  1989 znew.1.bz2&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin on peut copier le fichier et le décompresser :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code multi&amp;gt;&lt;br /&gt;
[mujma@localhost]#cp /usr/share/man/fr/man1/ls.1.bz2 $HOME&lt;br /&gt;
[mujma@localhost]#bunzip2 ls.1.bz2&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
==== Ouvrir un exemple ====&lt;br /&gt;
Enfin, si on ouvre ce fichier dans un éditeur de texte on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code multi&amp;gt;&lt;br /&gt;
.\&amp;quot; Traduction 19/12/1996 par Christophe Blaess (ccb@club-internet.fr)&lt;br /&gt;
.\&amp;quot; màj 04/01/1999 - LDP man-pages 1.22&lt;br /&gt;
.\&amp;quot; màj 03/01/2000&lt;br /&gt;
.\&amp;quot; màj 26/06/2000 - LDP man-pages 1.30&lt;br /&gt;
.\&amp;quot; màj 30/05/2001 - LDP man-pages 1.36&lt;br /&gt;
.\&amp;quot; màj 22/10/2002 - LDP man-pages 1.53&lt;br /&gt;
.\&amp;quot; MàJ 25/07/2003 LDP-1.56&lt;br /&gt;
.TH LS 1L &amp;quot;25 juillet 2003&amp;quot; LDP &amp;quot;Manuel de l&#039;utilisateur Linux&amp;quot;&lt;br /&gt;
.SH NOM&lt;br /&gt;
ls, dir, vdir \- Afficher le contenu d&#039;un répertoire.&lt;br /&gt;
.SH SYNOPSIS&lt;br /&gt;
.BI &amp;quot;ls [&amp;quot; options &amp;quot;] [&amp;quot; fichier... ]&lt;br /&gt;
.br&lt;br /&gt;
.BI &amp;quot;dir [&amp;quot; fichier... ]&lt;br /&gt;
.br&lt;br /&gt;
.BI &amp;quot;vdir [&amp;quot; fichier... ]&lt;br /&gt;
.sp&lt;br /&gt;
Options POSIX :&lt;br /&gt;
.BI &amp;quot;[\-CFRacdilqrtu1] [\-\-]&amp;quot;&lt;br /&gt;
.sp&lt;br /&gt;
Options GNU (forme courte) :&lt;br /&gt;
.B [\-1abcdfgiklmnopqrstuvwxABCDFGHLNQRSUX]&lt;br /&gt;
.BI &amp;quot;[\-w &amp;quot; cols ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  ... &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cette page documente la version de&lt;br /&gt;
.B ls&lt;br /&gt;
du paquetage fileutils-4.0. D&#039;autres versions peuvent diverger légèrement.&lt;br /&gt;
 &lt;br /&gt;
.SH TRADUCTION&lt;br /&gt;
Christophe Blaess, 1996-2003.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Faire un petit tour de groff ====&lt;br /&gt;
Avant de réellement comprendre la signification des codes étranges et barbares parfois situés en début de ligne, je vous invite maintenant à quitter votre éditeur pour rejoindre votre console.&lt;br /&gt;
&lt;br /&gt;
Nous allons maintenant faire quelques manipulations pratique sur le fichier ls.1 que nous avons recopier tout dernièrement dans notre répertoire de travail habituel.&lt;br /&gt;
&lt;br /&gt;
Tapez la commande suivante :&lt;br /&gt;
&amp;lt;code&amp;gt;[mujma@localhost]#groff -Tps -man ls.1 &amp;gt; ls.1.ps&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si groff est correctement installé (et il y a 99,9% de chances qu&#039;il le soit), vous devriez voir apparaître le fichier &amp;lt;tt&amp;gt;ls.1.ps&amp;lt;/tt&amp;gt; dans le répertoire courant.&lt;br /&gt;
&lt;br /&gt;
Vous pouvez le visualiser avec n&#039;importe quel afficheur postscript.&lt;br /&gt;
&lt;br /&gt;
Maintenant nous allons faire encore plus fort ! Pour cela tapez la commande :&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
[mujma@localhost]#groff -Thtml -man ls.1 &amp;gt; ls.1.html&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
De manière identique à la commande précédente, vous venez de générer un fichier html. Ouvrez-le vite... Oui, c&#039;est bien la documentation au format html.&lt;br /&gt;
Vous pouvez procéder ainsi avec toutes les pages de manuel linux !&lt;br /&gt;
En fait, groff est un préprocesseur. Il permet de générer les formats suivants à partir d&#039;une seule source :&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;dvi&#039;&#039;&#039; :  Pour ceux qui connaissent, c&#039;est le format TeX/LaTeX DVI.&lt;br /&gt;
; &#039;&#039;&#039;html&#039;&#039;&#039; : c&#039;est le format bien connu dont le nom signifie Hyper Text Markup Language et non, contrairement à ce que certains sous entendent parfois Hautes Technologies Mais Limitées.&lt;br /&gt;
; &#039;&#039;&#039;lbp&#039;&#039;&#039; : Format CAPSL pour les imprimantes laser Canon de type lbp-4 ou lpb-8.&lt;br /&gt;
; &#039;&#039;&#039;lj4&#039;&#039;&#039; : Format PCL5 pour imprimantes HP et compatibles.&lt;br /&gt;
; &#039;&#039;&#039;ps&#039;&#039;&#039; : Du vrai postscript bien de chez nous !&lt;br /&gt;
; &#039;&#039;&#039;ascii&#039;&#039;&#039; : C&#039;est le format ASCII 7-Bits, je le testerai peut-être cet hiver s&#039;il y a de la neige.&lt;br /&gt;
; &#039;&#039;&#039;cp1047&#039;&#039;&#039; : Historiquement destiné à certains serveurs internet et autres mainframes qui n&#039;ont toujours pas étés concurrencés par un certain Bill G. qui impose au monde le cp1250 dans les clicodrômes vitrés depuis la version nonante cinq , mais aussi langage natif de l&#039;imprimante qui vous sert peut-être aujourd&#039;hui de bac à fleurs, ce format implémente le jeux de caractères latin-1 en EBCDIC.&lt;br /&gt;
; &#039;&#039;&#039;latin1&#039;&#039;&#039; : C&#039;est le jeu de caractères ISO 8859-1 utilisé par exemple pour afficher des symboles mystérieux appartenant à l&#039;obscur langage qu&#039;étaient le François et le Français. On notera au passage qu&#039;il offre aussi l&#039;avantage d&#039;afficher des messages en &amp;quot;verlan&amp;quot; et en &amp;quot;nique ta m...&amp;quot; ou encore &amp;quot;nique ta r...&amp;quot; dialectes évolués de notre époque concurrençant le &amp;quot;slang&amp;quot; parlé dans les prisons anglo-saxonnes.&lt;br /&gt;
; &#039;&#039;&#039;utf8&#039;&#039;&#039; : C&#039;est le jeu de caractères Unicode UTF-8, similaire à celui du bios de votre machine.&lt;br /&gt;
&lt;br /&gt;
== groff et ses environnements ==&lt;br /&gt;
&lt;br /&gt;
Si l&#039;on se réfère à l&#039;invocation de &#039;&#039;&#039;groff&#039;&#039;&#039; dans l&#039;exemple précédent, groff est invoqué avec 3 paramètres en ligne de commande.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;groff -Thtml -m man ls.1 &amp;gt; ls.1.html&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
de manière plus générale on peut invoquer groff de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;groff -T&#039;&amp;lt;format_sortie&amp;gt;&#039; -m &#039;&amp;lt;format_entrée&amp;gt;&#039; &amp;gt; ls.1.html&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&amp;lt;format_sortie&amp;gt;&#039; correspond aux formats de sorties évoqués précédemment.&lt;br /&gt;
&lt;br /&gt;
&#039;&amp;lt;format_entrée&amp;gt;&#039; correspond au format utilisé pour écrire le source.&lt;br /&gt;
&lt;br /&gt;
Pour groff un format de sortie ou un format d&#039;entrée n&#039;est ni plus ni moins qu&#039;un ensemble de macros correspondant à des environnements.&lt;br /&gt;
&lt;br /&gt;
On trouve généralement les environnements (ou format d&#039;entrée) suivants avec le paquet groff :&lt;br /&gt;
&lt;br /&gt;
Les environnement macro dédiés au système de documentation :&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;man&#039;&#039;&#039; : format traditionnel des pages de manuel.&lt;br /&gt;
; &#039;&#039;&#039;mdoc&#039;&#039;&#039; : format BSD des pages de manuel.&lt;br /&gt;
; &#039;&#039;&#039;mandoc&#039;&#039;&#039; : cet environnement encapsule man et mdoc et permet de reconnaître le format du fichier d&#039;origine automatiquement.&lt;br /&gt;
&lt;br /&gt;
Pour des documents plus courants :&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;me&#039;&#039;&#039;, &#039;&#039;&#039;mm&#039;&#039;&#039; et &#039;&#039;&#039;ms&#039;&#039;&#039; : des environnements de génération de documents plus classiques (livres, rapports...).&lt;br /&gt;
&lt;br /&gt;
Pour générer des pages Web :&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;www&#039;&#039;&#039; : pour générer des documents &#039;HTML&#039;.&lt;br /&gt;
&lt;br /&gt;
== Où peut-on trouver des informations sur groff ==&lt;br /&gt;
&lt;br /&gt;
Les sites suivants vous apporterons diverses ressources pour &#039;&#039;&#039;groff&#039;&#039;&#039;:&lt;br /&gt;
* http://www.gnu.org/software/groff/groff.html&lt;br /&gt;
* http://www.troff.org/&lt;br /&gt;
* http://www.kohala.com/start/troff/troff.html&lt;br /&gt;
&lt;br /&gt;
{{Copy|2005|Marc UJMA|CC-BY-SA}}&lt;/div&gt;</summary>
		<author><name>BernardTV</name></author>
	</entry>
</feed>