GERBELOTBARILLON.COM

Parce qu'il faut toujours un commencement...

AWK

Du nom de ses créateurs Alfred AHO, Peter WEINBERGER, Brian KERNIGHAN, le langage AWK est disponible en standard dans les distributions Linux depuis de nombreuses années, étant donné que awk respecte la norme POSIX. Vérifiez la version de awk installée sur votre environnement par

$ awk -W version
	  
	  GNU Awk 5.2.1, API 3.2, PMA Avon 8-g1, (GNU MPFR 4.2.2, GNU MP 6.3.0)
	  Copyright © 1998, 1991-2022 Free Software Foundation.
	  
	  Ce programme est un logiciel libre ; vous pouvez le redistribuer et le
	  modifier selon les termes de la licence publique générale GNU (GNU
	  General Public License), telle que publiée par la Free Software
	  Foundation ; soit selon la version 3 de cette licence, soit selon une
	  version ultérieure de votre choix.
	  
	  Ce logiciel est distribué en espérant qu'il sera utile, mais SANS AUCUNE
	  GARANTIE, y compris les garanties implicites D'ADAPTATION À UN BUT
	  SPÉCIFIQUE et de COMMERCIALISATION. Pour plus d'informations à ce
	  sujet, consultez le texte de la licence publique générale GNU (GNU
	  General Public License).
	  
	  Vous devriez avoir reçu copie de la licence publique générale GNU
	  (GNU General Public License) avec ce programme. Sinon, consultez
	  http://www.gnu.org/licenses/.
      
Awk est un langage de script qui permet de manipuler simplement les fichiers au format texte avec une structure en colonnes séparées par des espaces ou des tabulations et terminées par des retours chariot..

Chaque ligne lue est stockée dans la variable $0, chaque partie de cette ligne étant séparée et répertoriée dans les variables $1 à $NF, en utilisant FS comme séparateur de champ (Field Separator) et RS comme séparateur d'enregistrement (Record Separator).

Dans les exemples qui vont suivre, nous utiliserons un fichier texte contenant ces éléments :

bob;adresse de bob;1 rue de nulle part
	  alice;adresse d'alice;2 rue de pas trouve
	  charles;adresse de charles;3 avenue de portenawak

Awk dispose d'un certain nombre de variables que l'on peut utiliser dans tous les scripts. Celles-ci n'ont pas besoin d'être initialisées et sont auto-typées. Certaines devront être initialisées avant d'être utilisées, comme le séparateur de champs (FS), dans la clause BEGIN du script.

VariableDescription
ARGCNombre d'arguments de la ligne de commande
ARGVTableau des arguments de la ligne de commande
CONVFMTFormat de conversion des nombres en chaine de caractères
ENVIRONTableau associatif des variables d'environnement
FILENAMENom du fichier courant
FNRNuméro de l'enregistrement parcouru dans le fichier courant
FSSéparateur de champs (par défaut espace, tabulation et retours chariots contigus [ \t\n]+)
NFNombre de champs de l'enregistrement courant
NRNuméro de l'enregistrement parcouru (tous fichiers confondus)
OFMTFormat de sortie des nombres
OFSSéparateur de champ en sortie (un espace)
ORSSéparateur d'enregistrement en sortie (nouvelle ligne)
RLENGTHLongueur du string trouvé par la fonction match()
RSSéparateur d'enregistrement (une nouvelle ligne)
RSTARTPremière position du string trouvé par la fonction match()
SUBSEPCaractère de séparation pour les routines internes des tableaux (\034)

Par exemple, nous pouvons récupérer le troisième champ du fichier fichier.txt, dans lequel chaque champ est séparé par un ';'. Afin de définir le séparateur, nous devons déclarer le bloc BEGIN avec la variable FS qui va contenir le séparateur ';'.

$ awk 'BEGIN{FS=";"} {print $3}' fichier.txt
	  1 rue de nulle part
	  2 rue de pas trouve
	  3 avenue de portenawak

Avant d'aller plus loin et d'obtenir des scripts Awk plus complexes, sachez que Awk peut accepter en entrée un fichier de commandes, ce qui sera beaucoup moins contraignant que de tout taper sur la ligne de commande (avec les tonnes d'erreurs à corriger...). Il suffit d'utiliser le paramètre -f fichier_script pour spécifier à Awk de prendre fichier_script comme source de script.

Ceci étant dit, Awk accepte le passage de valeurs en tant que paramètres dans le script. Par exemple si l'on suppose que nous avons un fichier contenant les commandes suivantes :

BEGIN{FS=";"; OFS=" : "}
	  $1 ~ nom {print $1, $3}
	  
	  $ awk -f fichier_script nom=alice fichier.txt
	  
	  alice : 2 rue de pas trouve
Si l'on analyse le fichier source, on voit que l'on va chercher les champs séparés par des ';'. Ces champs seront affichés séparés par ' : ' (paramètre OFS). Sur la seconde ligne, le caractère '~' (tilde) est utilisé comme une condition. En d'autres termes, si l'on a le paramètre nom qui est défini, alors on affiche les paramètres $1 et $3 (séparés par ' : ') et uniquement les lignes qui disposent de la correspondance du paramètre nom avec la valeur du champ $1. Et si cette variable nom n'est pas définie, alors toutes les lignes seront affichées.

Awk étant un outil de manipulation de fichier texte, il est normal de disposer d'un certain nombre de fonctions de manipulations de chaines de caractères.

FonctionDescription
gsub(exp, sub, str)Substitue l'expression exp par la chaine sub dans la chaine str. Renvoie le nombre de substitutions. Si str n'est pas défini, alors utilise le paramètre $0.
index(str, st)Retourne la position de la chaine st dans la chaine str, ou 0 si non trouvé.
length(str)Retourne la longueur de la chaine str, sinon renvoie la longueur de $0
match(str, exp)Retourne la position de l'expression régulière exp dans la chaine str, ou 0 si non trouvé. Affecte les valeurs aux variables RSTART et RLENGTH.
split(str, tab, sep)Sépare la chaine str en éléments dans un tableau tab en utilisant le séparateur sep. Si sep n'est pas défini, utilise la valeur de la variable FS.
sprintf("format", exp)Retourne une chaine au lieu de l'affichage vers la sortie standard.
sub(exp, sub str)Comme pour gsub() mais s'arrête à la première occurrence trouvée.
substr(str, pos, long)Retourne une partie du string str commençant à la position pos et de longueur long. Si long n'est pas définie, substr() utilise tout le reste de la chaine str.
tolower(str)Met en minuscule toute la chaine str et retourne la nouvelle chaine.
toupper(str)Idem tolower() mais en majuscules cette fois.

Awk dispose également de fonctions mathématiques pour les traitements numériques.

FonctionDescription
cos(r)Cosinus de l'angle r (en radians)
sin(r)Sinus de l'angle r (en radians)
exp(x)Exponentielle de x
log(x)Logarithme de x
sqrt(x)Racine carrée de x
atan2(x, y)Arc tangente de y/x
rand()Nombre pseudo-aléatoire entre 0 et 1.
srand(n)Réinitialise la fonction rand()
int(x)Valeur entière de x

En plus des fonctions prédéfinies, Awk accepte l'usage de fonctions personnelles dont la syntaxe est la suivante : elle commence par le mot-clé function suivie du nom de la fonction et de ses paramètres.

Pour faire des conditions et des boucles, utiliser if {} else if {} else {}. Les boucles sont faisables avec les constructions while(), do {} while() et for(initialisation;condition;increment) {}. Par exemple, si l'on veut savoir l'adresse de Bob :

BEGIN{FS=";"}
	  $0 ~ "bob" {
	    for (i=1; i <= NF; i++) {
	      if ($i == "adresse") print$(i+1)
	    }
	  }
      
Pour utiliser ce script, $ awk -f script.awk fichier.txt

Enfin, les tableaux associatifs (les dictionnaires comme définis dans d'autres langages),sont également disponibles. Ils ne requierent pas d'initialisation et constituent des tableaux à deux dimensions.


	  BEGIN{FS=";"}
	  {
	    if (nom == 0 || champ == 0) {
	    print "paramètres nom= et champ= sont obligatoires";
	      exit 1
	    }
	    remplir(tab)
	  }

	  function remplir(t){
	    for (i=2; i<=NF; i++) {
	      if ($i=="adresse") t[$1, "adresse"] = $(i + 1)
	      else if ($i == "vill") t[$1, "ville"] = $(i+1)
	    }
	  }
	  END {
	    if (nom != 0 && champ != 0)
	    if ((nom, champ) in tab) print nom, champ,":", tab[nom,champ]
	    else print nom, champ,"non trouvé"
			     
Ce code est à appeler par $ awk -f script.awk nom="alice" champ="adresse" fichier.txt ou bien par $ awk -f script.awk nom="bob" champ="ville" fichier.txt en ayant pris soin d'ajouter des champs au fichier texte d'origine par
bob;adresse;1 rue de nulle part;ville; somewhere
	  alice;adresse;2 rue de pas trouve;ville;nowhere
	  charles;adresse;3 avenue de portenawak;ville;what TF