# awk : quelques notes
awk lit les lignes d'un fichier dans l'ordre. Il vérifie si la ligne
répond à une condition et réalise dans ce cas des actions écrites entre
`{}`, sinon il passe à la ligne suivante.
La condition peut être un test sur une variable `(v == 2)`, ou bien
un test sur motif correspondant au texte de la ligne `/^Debut/`. Pour
plus de détails, regarder le man de
HTML re_format
qui explique les regex.
Par défaut, awk affiche la ligne sur la sortie standard.
Utiliser `END` permet d'exécuter des commandes (entre `{}`) à la fin du
script, `BEGIN` au début. Pratique pour définir des variables..
Exemple :
```
#!/usr/bin/awk -f
BEGIN { print "File\tOwner"}
{ print $8, "\t", $3}
END { print " - DONE -" }
```
## Variables spéciales
* `NF` : nombre de champs dans la ligne. `$(NF-2)` permet d'accéder à
l'élément 2 rangs avant le dernier.
* `NR` : numéro de ligne parsée.
* `FS` : ce qui sépare 2 champs. Par défaut, c'est un espace. On le
change au tout début avec `BEGIN{FS=":"}`
* `$0` représente toute la ligne.
On peut utiliser des variables sans les déclarer puis les afficher
ensuite. Par défaut, une variable non initialisée est vide : `""`.
## Patterns:
```
/admin/ { ... } # any line that contains 'admin'
/^admin/ { ... } # lines that begin with 'admin'
/admin$/ { ... } # lines that end with 'admin'
/^[0-9.]+ / { ... } # lines beginning with series of numbers and periods
/(POST|PUT|DELETE)/ # lines that contain specific HTTP verbs
```
## Actions et fonctions
* `next` : passe à la ligne suivante sans passer par les autres tests.
* `length(s)` : longueur de la chaîne s
* `gsub(r, t, s)` : remplace par t toute occurence de l'expression
régulière r dans la chaîne s.
Voir aussi le `man` de awk pour `match()`, `sub()`, `substr()`, ...
## getline
`getline()` permet de lire le contenu d'un autre fichier et
l'enregistrer en mémoire ou bien le traiter comme la ligne courante
`$0`. Chaque nouvel appel à `getline()` renvoie la ligne suivante
du fichier lu.
Il FAUT penser à fermer le fichier ET à vérifier que la lecture se
passe bien.
Par exemple, pour enregistrer dans "var" la première ligne de
"fichier.txt", on suivra la démarche suivante :
```
f = "fichier.txt"
if ((getline var < f) != 1 ) { next }
close(f)
```
On peut simuler la commande cat ainsi :
```
while ((getline < "fichier.txt") == 1) {
print
}
close("fichier.txt")
```
## Astuces diverses
On peut combiner les tests pour un pattern et une variable. Par
exemple, pour ne traîter QUE la 1ere ligne SI elle ne contient pas
"absent" :
```
apm | awk 'NR==1 && !/absent/ {printf " ⚡%s", $4}'
```
On peut définir toute une série de caractères comme délimiteurs. Par
exemple n'importe quelle lettre suivie de ":" :
```
uptime | awk -F'[a-z]:' '{print $2}'
```
Au lancement de awk, utiliser `-v var=value` permet de définir une
variable. Ce flag peut être utilisé plusieurs fois.
On peut concaténer des chaînes de caractères ainsi :
```
txt1 = "Hello"
txt2 = "World"
txt = txt1 " " txt2
# txt contient "Hello World"
```
On n'est pas obligé de prendre un fichier texte ou de lire l'entrée
standard. On peut aussi interpréter une liste passée en argument :
```
BEGIN {
for ( i = 1; i <= ARGC; i++ ) {
print ARGV[i]
}
exit
}
```
On peut ajouter des choses dans un tableau avec "++":
```
/aliases/ { hosts[$2]++ }
END {
for (h in hosts) print hosts[h], h
}
```
### trim avec awk
```
awk '{sub(/^[[:blank:]]+/, ""); sub(/[[:blank:]]+$/, ""); print }'
```
### Extraire une portion de texte situé à un index donné.
Il faut utiliser `match()` pour identifier l'emplacement du texte
cherché (dans la variable `RSTART`) puis utiliser `substr()` pour
extraire la portion voulue.
Par exemple pour récupérer le pourcentage du signal wifi.
```
match($0, "[0-9]+%")
if ( RLENGTH != -1 ) {
perc = substr($0,RSTART,RLENGTH)
}
print perc
```
### Simuler cut -f2- : afficher les colonnes suivantes
```
awk '1 {for (i = 2; i <= NF; i++;) {print $i}'
```
### Afficher ce qui est entre 2 pattern
```
awk '/PAT1/,/PAT2/' file
```
### Bien utiliser les regex
Dans sub(), gsub() ou autres, il vaut mieux éviter d'utiliser des regex
entre double quotes, mais plutôt entre "/".
Exemple :
```
gsub(/\.\.\//, "", p)
```
## Références
HTML URL:https://gregable.com/2010/09/why-you-should-know-just-little-awk.html
HTML URL:https://ferd.ca/awk-in-20-minutes.html
HTML URL:https://github.com/minhhh/wiki/blob/master/awk.md