Table of Contents

awk

C'est un langage de manipulation de chaînes de caractères d'un fichier ou d'un flux en entrée.

Les différentes commandes que l'on peut passer sont de la forme motif { action }. awk traite séquentiellement le flux de caractères (fichier en paramètre ou flux en entrée) par ligne (enregistrement) et colonne (champ) ; on peut récupérer les colonnes avec les variables $1, $2, .., $10 ,$NF (dernière colonne) et $0 qui correspond à la ligne complète. Les champs peuvent être spécifiés par des expressions, comme $(NF-1) pour l'avant dernier champs.

Le motif

Pour utiliser une variable bash comme regexp avec awk, on peut procéder ainsi :

awk '$1 ~ /^'$VAR'/ {print}'

Les options

vi test.awk
BEGIN{FS=";"; OFS=" : "}
$0 ~ "test" {print $0}
:x
 
awk -f test.awk fichier.txt
 ceci est un test
echo "toto;tata-titi" | awk -F":|-" '{print $1" "$2" "$3}'
 toto tata titi
HOST=toto ; echo titi | awk -v h=$HOST '{print "h="h}'
 h=toto

Autre façon de passer des variables dans un fichier de script :

vi test.awk
BEGIN{FS=";"; OFS=" : "}
$0 ~ rechch {print $0}
:x
 
awk -f test.awk rechch=test fichier.txt
 ceci est un test

Les variables prédéfinies

Variable Description Valeur par défaut
ARGC nombre d'arguments de la ligne de commande
ARGV tableau des arguments de la ligne de commande
FILENAME nom du fichier sur lequel on applique les commandes
ENVIRON tableau associatif des variables d'environnement
FNR nombre d'enregistrements parcourus du fichier courant
FS séparateur de champs (en entrée) <tab>, <espace> ou <retour chariot> contigus
NF nombre de champs de l'enregistrement courant
NR nombre d'enregistrements parcouru (tous fichiers confondus)
OFMT format de sortie des nombres
OFS séparateur de champs pour la sortie <espace>
ORS séparateur d'enregistrement pour la sortie <retour chariot>
RLENGTH longueur de la chaine trouvée
RS séparateur d'enregistrement en entrée <retour chariot>
RSTART début de la chaine trouvée
SUBSEP séparateur de subscript

Les fonctions texte

Les paramètres sont soit des chaines de caractères (s et t), soit des regexp ® soit des entiers (i et n).

Le cas printf

printf et ses dérivées sont des fonctions d'affichage de texte qui permettent de formater la sortie (pour un résultat bien léché comme on aime). Voici quelques cas d'utilisation commentés :

# afficher les logins et description des utilisateurs locaux qui utilisent le shell /bin/bash
# en alignant les logins à droite et sur 20 caractères
awk -F: '$7 ~ /\/bin\/bash/ {printf "%-20s %s\n", $1, $5}' /etc/passwd
root                 root
dude                 a dude
robert               le gros robert
 
# puisque l'affichage est par colonne, on va afficher les noms pour être plus parlant
# on utilise l'instruction BEGIN qui, comme on l'a vu, ne s'exécute qu'une fois en début de script
awk -F: 'BEGIN {printf "%-20s %s\n", "login:","description:"} $7 ~ /\/bin\/bash/ {printf "%-20s %s\n", $1, $5}' /etc/passwd
login:               description:
root                 root
dude                 a dude
robert               le gros robert
 
# on peut même définir un format d'affichage pour ne pas avoir a le retaper à chaque printf :
awk -F: 'BEGIN {format = "%-20s %s\n"; printf format, "login:","description:"; printf format, "---","---"} $7 ~ /\/bin\/bash/ {printf format, $1, $5}' /etc/passwd
login:               description:
---                  ---
root                 root
dude                 a dude
robert               le gros robert
 
# la même commande, en plus lisible :
awk -F: 'BEGIN {format = "%-10s %s\n"
	printf format, "login:","description:"
	printf format, "---","---"}
	$7 ~ /\/bin\/bash/ {printf format, $1, $5}' /etc/passwd

Les fonctions mathématiques

cos(x), exp(x), int(x), log(x), sin(x), sqrt(x), atan2(x,y), rand(x), srand(x)

Exemples

awk -F ":" '{ $2 = "" ; print $0 }' /etc/passwd
awk 'END {print NR}' /etc/passwd
awk '{if (NR==3) print}' <fichier>
awk '{print $NF}' /etc/passwd
who | awk '{print $1,$5}'
awk 'length($0)>75 {print}' /etc/passwd
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
echo "toto.domaine.fr est un nom trop long !" | awk 'gsub(/\..*$/,"",$1) {print "machine="$1}'
awk '/BEGIN/,/END/' FILE.txt
awk '!x[$0]++' test.tmp
echo -e "toto\ntoto\n" | awk '/toto/ {print; exit}'
 toto
echo -e "toto   :titi\n   tata:tutu" | \
 awk -F\: '{ sub(/^[ \t\r\n]+/, "", $1);sub(/[ \t\r\n]+$/, "", $1);print "\""$1"\""}'
# count s'incrémente à chaque ligne déjà rencontrée ; on n'affiche donc la ligne qu'à sa première apparition
awk '!(count[$0]++)' fic.txt
echo $ligne | awk -F'k' '{print NF-1}'
awk 'NR%2==0' fic.txt