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.
Pour utiliser une variable bash comme regexp avec awk, on peut procéder ainsi :
awk '$1 ~ /^'$VAR'/ {print}'
-f <fichier>
précise un fichier de script awkvi test.awk BEGIN{FS=";"; OFS=" : "} $0 ~ "test" {print $0} :x awk -f test.awk fichier.txt ceci est un test
-F “<séparateur>”
spécifie le séparateur de champs (“ ” (espace) par défaut). NB : on peut spécifier plusieurs séparateurs en les séparant par “|” :echo "toto;tata-titi" | awk -F":|-" '{print $1" "$2" "$3}' toto tata titi
-v var=“val”
: permet d'affecter une valeur val à une variable var avant la partie BEGINHOST=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
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 paramètres sont soit des chaines de caractères (s et t), soit des regexp ® soit des entiers (i et n).
gsub(r,s,t)
: sur la chaine t, remplace toutes les occurrence de r par sindex(s,t)
: retourne la position la plus à gauche de la chaine t dans la chaine slength(s)
: retourne la longueur de la chaine smatch(s,r)
: retourne l'index ou s correspond à r et positionne RSTART et RLENTHsplit(s,a,fs)
: split s dans le tableau a sur fs, retourne le nombre de champssprintf(fmt,liste expressions)
: retourne la liste des expressions formatée suivant fmtsub(r,s,t)
: comme gsub, mais remplace uniquement la première occurrencesubstr(s,i,n)
: retourne la sous chaine de s commençant en i et de taille ntolower(s)
: passer la chaîne en minusculestoupper(s)
: passer la chaîne en majusculescount[s]
: compte le nombre d’occurrence de sprintf 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
cos(x), exp(x), int(x), log(x), sin(x), sqrt(x), atan2(x,y), rand(x), srand(x)
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}'
print
équivaut à print $0
)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