retour sur @lyon coup de coeur du jour discussion roulette meteo locale La commande awk retour
editorial contact par mail

 

Cette commande permet d'appliquer un certain nombre d'actions sur un fichier. La syntaxe est inspirée du C

syntaxe :
awk [-Fs] [-v variable] [-f fichier de commandes] 'program' fichier
-F  Spécifie les séparateurs de champs 
-s  ??? 
-v  Définie une variable utilisée à l'intérieur du programme. 
-f  Les commandes sont lu à partir d'un fichier. 
principe de fonctionnement :
Un enregistrement est une chaine de caractères séparée par un retour chariot.
Un champs est une chaine de caractères separée par un espace (ou par le caractère specifié par l'option -F)
La variable NF contient le nombre de champs de l'enregistrement courant. On accède à chaque champs par la variable $1, $2, ... $NF. $0 correspond à l'enregistrement complet. Le programme est une suite d'action de la forme : motif { action }

 
examples: 
awk -F ":" '{ $2 = "" ; print $0 }' /etc/passwd  imprime chaque ligne du fichier /etc/passwd après avoir effacé le deuxième champs
awk 'END {print NR}' fichier  imprime le nombre total de lignes du fichiers
awk '{print $NF}' fichier  imprime le dernier champs de chaque ligne
who | awk '{print $1,$5}'  imprime le login et le temps de connexion.
awk 'length($0)>75 {print}' fichier  imprime les lignes de plus de 75 caractères. (print équivaur à print $0) 

Les variables prédéfinies

Variable  Signification  Valeur par défaut 
ARGC  Nombre d'arguments de la ligne de commande 
ARGV  tableau des arguments de la ligne de commnde 
FILENAME  nom du fichier sur lequel on applique les commandes 
FNR  Nombre d'enregistrements du fichier 
FS  separateur de champs en entrée  " " 
NF  nombre de champs de l'enregistrement courant 
NR  nombre d'enregistrements deja lu 
OFMT  format de sortie des nombres  "%.6g" 
OFS  separateur de champs pour la sortie  " " 
ORS  separateur d'enregistrement pour la sortie  "\n" 
RLENGTH  longueur de la chaine trouvée 
RS  separateur d'enregistrement en entrée  "\n" 
RSTART  debut de la chaine trouvée 
SUBSEP  separateur de subscript  "\034" 

Syntaxe du motif

Si le motif existe, cela determine si l'action doit être appliquée à la ligne ou non.
Le motif peut etre : examples:
 awk 'BEGIN { print "Verification des UID et GID dans le fichier /etc/passwd";
              FS=":"}
      $3 !~ /^[0-9][0-9]*$/ {print "UID  erreur ligne "NR" :\n"$0 }
      $4 !~ /^[0-9][0-9]*$/ {print "GID  erreur ligne "NR" :\n"$0 }
      END   { print "Fin" }
' /etc/passwd
Résultat :
Verification des UID et GID dans le fichier /etc/passwd
UID erreur ligne 14 :
clown:*:aaa:b:utilisateur en erreur:/home/clown:/bin:sh
GID erreur ligne 14 :
clown:*:aaa:b:utilisateur en erreur:/home/clown:/bin/sh
Fin
 awk 'BEGIN { print "Verification du fichier /etc/passwd pour ...";
              print "- les utilisateurs avec UID = 0 " ;
              print "- les utilisateurs avec UID >= 60000" ;
              FS=":"}
      $3 == 0 { print "UID 0 ligne "NR" :\n"$0 }
      $3 >= 60000  { print "UID >= 60000 ligne "NR" :\n"$0 }
      END   { print "Fin" }
' /etc/passwd
Résultat :
Verification du fichier /etc/passwd pour ...
- les utilisateurs avec UID = 0
- les utilisateurs avec UID >= 60000
UID 0 ligne 5 :
root:*:0:b:administrateur:/:/bin/sh
UID >= 60000 ligne 14 :
clown:*:61000:b:utilisateur en erreur:/home/clown:/bin/sh
Fin

 

 awk 'BEGIN { print "Verification du fichier /etc/group";
              print "le groupe 20 s'appelle t-il bien users ? " ;
              FS=":"}
      $1 == "users" && $3 ==20 { print "groupe "$1" a le GID "$3" !" }
      END   { print "Fin" }
' /etc/group
Résultat :
Verification du fichier /etc/group
le groupe 20 s'appelle t-il bien users ?
groupe users a le GID 20 !
Fin
 awk 'NR == 5 , NR == 10 {print NR" : " $0 }' fichier
Imprime de la ligne 5 à la ligne 10 , chaque ligne précédée par son numéro

 

Syntaxe de l'action

Une action transforme ou manipule des données. par défaut print
type des actions

Fonctions numériques

Nom des fonctions  signification 
atan2(y,x)  arctangente de x/y en redians dans l'interval -pi pi
cos(x)  cosinus (en radians) 
exp(x)  exponentielle e à la puissance x
int(x)  valeur entière 
log(x)  logarythme naturel 
rand()  nombre aléatoire entre 0 et 1 
sin(x)  sinus (en radians) 
sqrt(x)  racine carrée 
srand(x)  reinitialiser le générateur de nombre aléatoire 

Les fonctions sur les chaines de caractères

Dans le tableau suivant :
s et t represente des chaines de caractères
r une expression régulière
i et n des entiers
Nom des fonctions  signification 
gsub(r,s,t)  sur la chaine t, remplace toutes les occurance de r par s 
index(s,t)  retourne la position la plus à gauche de la chaine t dans la chaine s
length(s)  retourne la longueur de la chaine s 
match(s,r)  retourne l'index ou s correspond à r et positionne RSTART et RLENTH 
split(s,a,fs)  split s dans le tableau a sur fs, retourne le nombre de champs 
sprintf(fmt,liste expressions)  retourne la liste des expressions formattée suivant fmt 
sub(r,s,t)  comme gsub, mais remplce uniquement la première occurence 
substr(s,i,n)  retourne la sous chaine de s commencant en i et de taille n 

Les variables et expressions

Les opérations et affectations arithmétiques
Les opérations arithmétiques
Les variables de champs
Rappel : Les champs de la ligne courant sont : $1, $2, ..., $NF
La ligne entière est $0
Ces variables ont les memes propriétés que Les autres variables. Elles peuvent etre reaffectées. Quand $0 est modifiées, les variables $1,$2 ... sont aussi modifiées ainsi que NF.Inversement si une des variables $i est modifiées, $0 est mise à jour.
Les champs peuvent etre specifiés par des expressions, comme $(NF-1) pour l'avant dernier champs.
example:
 awk 'BEGIN { FS=":" ;
             OFS=":"}
      $NF != "/bin/ksh" { print $0 }
      $3 == "/bin/ksh" && NF == 7  { $7 = "/bin/posix/sh" ;
                                     print $0 } '
      /etc/passwd > /etc/passwd.new
Résultat :
On crée un nouveau fichier de mot de passe /etc/passwd.new en remplacant le shell /bin/ksh par /bin/posix/sh

 

concaténation de chaines de caractères
Il n'y a pas d'opérateur de concaténation, il faut simplement lister les chaines à concaténer.
examples:
 awk '{ print NR " : " $0 }' fichier
Résultat :
On numérote les lignes du fichier
 awk 'BEGIN { FS=":" ;
             OFS=":" ;
             print " Run Level 2 : Liste des actions "}
      $2 ~ /2/  { print "Keyword <<"$3">>, \n Tache <<"$4">>" }
      $2 == ""  { print "Keyword <<"$3">>, \n Tache <<"$4">>" }
' /etc/inittab > /etc/passwd.new
Résultat :
Affiche les actions executées lors du passage à l'état 2

 

while

Syntaxe: while ( condition ) action

for

breack, continue

Break: sortie de boucle
Continue: commence une nouvelle itération de la boucle.

if , else

Syntaxe:
if ( expression ) action
else action

commentaire et action vide

Le commentaire est précédé par #. tout ce qui est entre # et la fin de la ligne est ignoré par awk
Une action vide est représenté par ;

next, exit

Next: passe à l'enregistrement suivant. On reprend le script awk à son début
Exit: ignore le reste de l'entrée et execute les actions définie par END

affichage

print exp, exp ou print (exp , exp ) affiche les expressions
print equivaut à print $0
printf format , exp, exp ou printf (format,exp , exp ) identique à print mais en utilisant un format (voir printf en C)
Un format est une chaine de caractères et des constructeurs commencant par %
specifieur  signification 
nombre decimal 
chaine de caractères 
 
specifieur  signification 
expression justifiée à gauche 
largeur  largeur d'affichage 
.precision  longueur maximale d'une chaine de caracteres 
ou nombre de decimales 
Example:
La sortie d'un print ou d'un printf peut être redirigée dans un fichier ou sur un pipe
Les noms de fichiers doivent être entre guillemets sinon ils sont considérés comme des variables
Example:
awk ' { print NR " :" , $0 > "fich.numerote" } ' fichier  le fichier fich.numerote contient le fichier fichier avec les lignes numérotées

 

awk ' { printf "%3d : %s " , NR , $0 > "fich.numerote" } ' fichier  le fichier fich.numerote contient le fichier fichier avec les lignes numérotées sur 3 caractères

tableau

On peut utiliser des tableaux de chaines de caractères et de nombres à une dimension
Il n'est pas nécessaire de les déclarer. La valeur par défaut est "" ou 0 .
Les indices sont des chaines de caractères.
 awk 'BEGIN { print "Mémorisation de votre fichier " FILENAME }
                 {memfile [NR] = $0 }
           END   { for ( i = NR ; i >= 1 ; i-- ) {
                    print i ":" memfile[i]
                    }
                  print "Fin"
                 } ' fichier
Résultat :
Affiche le fichier en commencant par la derniere ligne

 

 awk ' NF > 0 {
                    for (i=1;i<=NF;i++) {
                        if ( $i ~ /^[0-9a-zA-Z][0-9a-zA-Z]*$/ ) {
                            index[$i] = index[$i] ";" NR "," i " " ;
                            index["total"]++ ;
                            }
                        }
                     }
            END     { x="total" ;
                      printf("%s mots detectés = %d\n",x,index[x]);
                      } ' fichier
Résultat :
Construction d un index de cross reference

 

for et les tableaux

Comme les indices des tableaux sont des chaines de caractères, on ne peut pas determiner la taille d'un tableau
On doit donc utiliser la construction :
 for (var in tableau)
action
 awk ' NF > 0 {
                    for (i=1;i<=NF;i++) {
                        if ( $i ~ /^[0-9a-zA-Z][0-9a-zA-Z]*$/ ) {
                            index[$i] = index[$i] ";" NR "," i " " ;
                            index["total"]++ ;
                            }
                        }
                     }
            END     {
                    for ( x in index ) { 
                     if ( x != "total" )
                       printf("%-20s\t%s\n",x,index[x]) | "sort -f "
                      }
                      x="total";
                      printf("%s mots detectés = %d\n",x,index[x]);
                      } ' fichier
Résultat :
Construction d un index de cross reference

 

simulations des tableau multidimensions

On ne peut pas utiliser des tableaux multidimentionnels.
On peut les simuler en concatenant des composants des sous chaines avec le séparateur SUBSEP
 awk 'BEGIN { print "Mémorisation de votre fichier " FILENAME 
                   SUBSEP=":" 
                 }
                 {  for ( i=1 ; i <=NF ; i++ ) {
                    memfields[ NR , i ] = $i
                    }
                 }
           END   { for ( i in memfields ) {
                    print i ":" memfields[i] | "sort -n -t: "
                    }
                  print "Fin"
                 } ' fichier
Résultat :
Affiche le fichier en commencant par la derniere ligne