Libère le potentiel de ton terminal avec la commande AWK.
AWK est un formidable outil qui te permet de tordre à ta guise les outputs de ton terminal.
Je vais te donner les bases pour afficher et modifier les sorties de ton terminal.
Si je fais un simple ls -l voici le résultat :
ls -l
total 4
-rwxr-xr-x 1 babidi babidi 540 mars 26 2020 delete.sh
-rw-rw-r-- 1 babidi babidi 0 oct. 10 21:10 fichier_test
-rw-rw-r-- 1 babidi babidi 0 oct. 10 21:10 mot_start.sh
-rw-rw-r-- 1 babidi babidi 0 oct. 10 21:10 test
Affiche le champs souhaité du retour d’une commande:
awk '{print $numéro de champs}'
Exemple :
Nous allons utiliser la commande ls –l et nous voulons n’afficher que le propriétaire du fichier et le nom de fichier :
ls -l | awk '{print $3 " " $9}'
babidi delete.sh
babidi fichier_test
babidi mot_start.sh
babidi test
Ici j’ai décidé d’afficher le 3eme champs puis un espace et enfin le champs 9.
$0 | toute la ligne |
$1 | premier champ |
$3 | troisième champ |
$12 | douzième champ |
On peut donc afficher le champs que l’on veut dans l’ordre que l’on veut et ajouter des chaines de caractères n’importe où.
Utiliser le délimiteur de son choix
J’ai utilisé le délimiteur par défaut qui est la tabulation mais j’aurais également pu utiliser le délimiteur de mon choix avec l’argument FS=. Exemple: FS= »: » pour utiliser « : » comme délimiteur.
Si je prend le fichier passwd :
tail /etc/passwd
tcpdump:x:129:138::/nonexistent:/usr/sbin/nologin
nm-openvpn:x:130:141:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
systemd-coredump:x:997:997:systemd Core Dumper:/:/usr/sbin/nologin
tss:x:131:142:TPM software stack,,,:/var/lib/tpm:/bin/false
_rpc:x:132:65534::/run/rpcbind:/usr/sbin/nologin
statd:x:133:65534::/var/lib/nfs:/usr/sbin/nologin
libvirt-qemu:x:64055:139:Libvirt Qemu,,,:/var/lib/libvirt:/usr/sbin/nologin
libvirt-dnsmasq:x:134:144:Libvirt Dnsmasq,,,:/var/lib/libvirt/dnsmasq:/usr/sbin/nologin
snapd-range-524288-root:x:524288:524288::/nonexistent:/bin/false
snap_daemon:x:584788:584788::/nonexistent:/bin/false
Si je souhaite afficher le premier et le troisième champ, je peux faire :
awk '{print $1" "$3}' FS=":" /etc/passwd
passwd
root 0
daemon 1
bin 2
sys 3
sync 4
games 5
man 6
lp 7
mail 8
news 9
uucp 10
proxy 13
www-data 33
...
Transformer l’output avec awk
Tu remarqueras que j’ai modifier la sortie avec les » « .
Je peux totalement transformer le visuel de sortie à ma guise, exemple :
awk '{print "username:" $1 " uid:" $3}' FS=":" /etc/passwd
username:root uid:0
username:daemon uid:1
username:bin uid:2
username:sys uid:3
username:sync uid:4
username:games uid:5
username:man uid:6
username:lp uid:7
username:mail uid:8
username:news uid:9
username:uucp uid:10
username:proxy uid:13
username:www-data uid:33
Tu commences à comprendre la puissance de l’outil ? 😏
Afficher le nombre de ligne:
L’expression NR signifie le numéro de ligne, voici donc comment afficher le numéro de ligne :
ls -l | awk '{print "ligne " NR " " $0}'
ligne 1 total 16
ligne 2 -rwxr-xr-x 1 babidi babidi 540 mars 26 02:08 delete.sh
ligne 3 -rw-r--r-- 1 babidi babidi 466 mai 6 20:03 fichier_test
ligne 4 -rwxr-xr-x 1 babidi babidi 255 mai 6 20:28 mot_start.sh
ligne 5 drwxr-xr-x 2 babidi babidi 4096 mars 26 02:08 test
Remarque : la variable $0 dans la commande awk signifie l’intégralité de la ligne.
Afficher le nombre de champs:
ls -l | awk '{print "nombre de champs " NF " " $0}'
nombre de champs 2 total 16
nombre de champs 9 -rwxr-xr-x 1 babidi babidi 540 mars 26 02:08 delete.sh
nombre de champs 9 -rw-r--r-- 1 babidi babidi 466 mai 6 20:03 fichier_test
nombre de champs 9 -rwxr-xr-x 1 babidi babidi 255 mai 6 20:28 mot_start.sh
nombre de champs 9 drwxr-xr-x 2 babidi babidi 4096 mars 26 02:08 test
Là on demande d’afficher « nombre de champs » + NF qui correspond au numéro de champs + un espace » » + $0 qui afficher toute la ligne
Les conditions
Avec les conditions on peux extraire exactement ce qu’on veut.
Je veux extraire les lignes ou le premier champ est « postgres » :
awk '{ if($1 == "postgres") print "username:" $1 " uid:" $3}' FS=":" /etc/passwd
username:postgres uid:123
Pareil mais avec un else if :
awk '{ if($1 == "postgres") print "username:" $1 " uid:" $3; else if($1 == "mysql") print "username:" $1 " uid:" $3}' FS=":" /etc/passwd
username:postgres uid:123
username:mysql uid:127
On aurait pu faire pareil et plus court avec le or « || » :
awk '{ if($1 == "postgres" || $1 == "mysql") print "username:" $1 " uid:" $3}' FS=":" /etc/passwd
username:postgres uid:123
username:mysql uid:127
Une condition pour afficher les lignes ou le premier champs contient « oo » :
awk '$1 ~ /oo/ { print "username:" $1 " uid:" $3}' FS=":" /etc/passwd
username:root uid:0
username:whoopsie uid:109
username:kernoops uid:116
username:snapd-range-524288-root uid:524288
Si je souhaite afficher les lignes qui finissent en /bin/false :
awk '$7 ~ /bin\/false$/ { print "username:" $1 " uid:" $3}' FS=":" /etc/passwd
username:systemd-timesync uid:100
username:systemd-network uid:101
username:systemd-resolve uid:102
username:syslog uid:104
username:_apt uid:105
username:messagebus uid:106
username:uuidd uid:107
username:lightdm uid:108
username:whoopsie uid:109
username:avahi-autoipd uid:110
username:avahi uid:111
username:dnsmasq uid:112
$ correspond à la fin de la ligne.
Substitution d’une chaine de caractères:
La commande gsub permet de subtituer une chaine de caractères par une autre sur les colonnes de notre souhait.
Exemple, utiliser la commande ls et substituer le nom d’utilisateur par un autre:
ls -l | awk '{gsub("babidi","BOSS",$0);print $0}'
total 16
-rwxr-xr-x 1 BOSS BOSS 540 mars 26 02:08 delete.sh
-rw-r--r-- 1 BOSS BOSS 466 mai 6 20:03 fichier_test
-rwxr-xr-x 1 BOSS BOSS 255 mai 6 20:28 mot_start.sh
drwxr-xr-x 2 BOSS BOSS 4096 mars 26 02:08 test
Calcul de statistique
awk '{somme+=$1} END {print somme}' nom_du_fichier
Ici on calcule la somme de la première colonne de chaque ligne et on affiche cette somme en fin de ligne.
Fusion de fichier
awk '{print}' fichier1.txt fichier2.txt > fichier_fusionne.txt
On fusionne fichier1.txt et fichier2.txt.
Il est aussi possible de rajouter des conditions pour récolter dans le fichier_fusionne.txt seulement les lignes intéressantes.
Tri
Par exemple si on veut trier les utiisateurs (fichier /etc/passwd) par leurs UID on peut utiliser la commande awk :
awk -F: '{print $1, $3}' /etc/passwd | sort -n -k2
En associant awk avec d’autres commande (ici sort) on peut facilement aller beaucoup plus loin dans l’affichage et l’organisation des données.
AWK et la boucle for
Il est possible d’afficher un fichier via une boucle for :
awk '{for (i=1; i<=NF; i++) {print $i}}' nom_du_fichier
Dans cette commande le nombre de champs est stocké dans la variable « NF ».
La boucle for parcourt les champs de 1 à NF et à chaque itération on affiche $i (chaque mot donc).
Si on rajoute des conditions on peux ajouter/modifier/supprimer des éléments à notre guise.
Exemples d’utilisations
- Extraction de colonnes spécifiques d’un fichier
- Sélection des lignes qui contiennent un mot spécifique
- Calcul de statistiques sur les données
- Formatage de données
- Fusion de plusieurs fichiers
- Sélection des lignes qui respectent une/des conditions
- Substitution de caractères
- Tri
- Comptage de pattern
La doc complète de awk => https://www.gnu.org/software/gawk/manual/gawk.html
Besoin d’aide ?
Tu as besoin de conseil ou d’assistance pour un problème technique ou la conception d’un script, tu peux nous contacter ICI nous essayerons de t’apporter notre aide.
Si l’article t’a intéressé, n’hésites pas à le partager pour en faire profiter à tous.
⬇️