formattage awk

10 réponses
Avatar
Lulu
[xp : fcolc,fcou ; fu2 :fcou ]

[supersedes : erreur dans mon sed]

Yo !

Je suis en train d'écrire un one-liner qui donne le nombre d'octets
envoyés par l'interface réseau :

$ cat /proc/net/dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 40750160 55083 0 0 0 0 0 0 40750160 55083 0 0 0 0 0 0
wlp2s0: 400565197 508500 0 142 0 0 0 0 177714515 445447 0 0 0 0 0 0

$ grep wlp2s0 /proc/net/dev | awk -F ' ' '{print $10}'
178064693

$ grep wlp2s0 /proc/net/dev | awk -F ' ' '{print $10}' | rev | sed -E 's/.../& /g' | rev
178 065 488

Je passe par rev et sed car je n'ai rien compris au formattage de chaîne avec
awk.

(rev est nécessaire pour que '1234' donne bien '1 234' et non '123 4')


Merci de votre aide.

10 réponses

Avatar
Benoit Izac
Bonjour,
Le 28/03/2020 à 20:44, Lulu a écrit dans le message
 :
Je suis en train d'écrire un one-liner qui donne le nombre d'octets
envoyés par l'interface réseau :
$ cat /proc/net/dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 40750160 55083 0 0 0 0 0 0 40750160 55083 0 0 0 0 0 0
wlp2s0: 400565197 508500 0 142 0 0 0 0 177714515 445447 0 0 0 0 0 0
$ grep wlp2s0 /proc/net/dev | awk -F ' ' '{print $10}'
178064693
$ grep wlp2s0 /proc/net/dev | awk -F ' ' '{print $10}' | rev | sed -E 's/.../& /g' | rev
178 065 488
Je passe par rev et sed car je n'ai rien compris au formattage de chaîne avec
awk.
(rev est nécessaire pour que '1234' donne bien '1 234' et non '123 4')

LC_NUMERIC=fr_FR printf "%'.f" $(awk '/wlp2s0/{print $10}' /proc/net/dev)
--
Benoit Izac
Avatar
Philippe Weill
Le 28/03/2020 à 20:44, Lulu a écrit :
[xp : fcolc,fcou ; fu2 :fcou ]
[supersedes : erreur dans mon sed]
Yo !
Je suis en train d'écrire un one-liner qui donne le nombre d'octets
envoyés par l'interface réseau :
$ cat /proc/net/dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 40750160 55083 0 0 0 0 0 0 40750160 55083 0 0 0 0 0 0
wlp2s0: 400565197 508500 0 142 0 0 0 0 177714515 445447 0 0 0 0 0 0
$ grep wlp2s0 /proc/net/dev | awk -F ' ' '{print $10}'
178064693
$ grep wlp2s0 /proc/net/dev | awk -F ' ' '{print $10}' | rev | sed -E 's/.../& /g' | rev
178 065 488
Je passe par rev et sed car je n'ai rien compris au formattage de chaîne avec
awk.
(rev est nécessaire pour que '1234' donne bien '1 234' et non '123 4')
Merci de votre aide.

[ ~]$ cat /tmp/testawk.awk
{ printf "%'dn",$0 }
[ ~]$ echo 123456789 | LC_NUMERIC="C" gawk -f /tmp/testawk.awk
123456789
[ ~]$ echo 123456789 | LC_NUMERIC="fr_FR.UTF-8" gawk -f /tmp/testawk.awk
123 456 789
[ ~]$ echo 123456789 | LC_NUMERIC="en_US.UTF-8" gawk -f /tmp/testawk.awk
123,456,789
[ ~]$
Avatar
Benoit Izac
Bonjour,
Le 29/03/2020 à 11:28, Philippe Weill a écrit dans le message
<r5ppng$m1d$ :
Je suis en train d'écrire un one-liner qui donne le nombre d'octets
envoyés par l'interface réseau :
$ cat /proc/net/dev
[...]
$ grep wlp2s0 /proc/net/dev | awk -F ' ' '{print $10}'
178064693
$ grep wlp2s0 /proc/net/dev | awk -F ' ' '{print $10}' | rev | sed
-E 's/.../& /g' | rev
178 065 488
Je passe par rev et sed car je n'ai rien compris au formattage de
chaîne avec
awk.
(rev est nécessaire pour que '1234' donne bien '1 234' et non '123
4')

[ ~]$ cat /tmp/testawk.awk
{ printf "%'dn",$0 }
[ ~]$ echo 123456789 | LC_NUMERIC="C" gawk -f /tmp/testawk.awk
123456789
[ ~]$ echo 123456789 | LC_NUMERIC="fr_FR.UTF-8" gawk -f
/tmp/testawk.awk
123 456 789
[ ~]$ echo 123456789 | LC_NUMERIC="en_US.UTF-8" gawk -f
/tmp/testawk.awk
123,456,789
[ ~]$

Cool, en one shot ça donne donc :
LC_NUMERIC=fr_FR.UTF-8 gawk '/wlp2s0/{printf "%'"'"'dn", $10}' /proc/net/dev
--
Benoit Izac
Avatar
Lulu
Le 29-03-2020, Benoit Izac a écrit :
Le 29/03/2020 à 11:28, Philippe Weill a écrit dans le message
<r5ppng$m1d$ :
Je suis en train d'écrire un one-liner qui donne le nombre d'octets
envoyés par l'interface réseau :
$ cat /proc/net/dev
[...]
$ grep wlp2s0 /proc/net/dev | awk -F ' ' '{print $10}'
178064693
$ grep wlp2s0 /proc/net/dev | awk -F ' ' '{print $10}' | rev | sed
-E 's/.../& /g' | rev
178 065 488
Je passe par rev et sed car je n'ai rien compris au formattage de
chaîne avec
awk.
(rev est nécessaire pour que '1234' donne bien '1 234' et non '123
4')

[ ~]$ cat /tmp/testawk.awk
{ printf "%'dn",$0 }
[ ~]$ echo 123456789 | LC_NUMERIC="C" gawk -f /tmp/testawk.awk
123456789
[ ~]$ echo 123456789 | LC_NUMERIC="fr_FR.UTF-8" gawk -f
/tmp/testawk.awk
123 456 789
[ ~]$ echo 123456789 | LC_NUMERIC="en_US.UTF-8" gawk -f
/tmp/testawk.awk
123,456,789
[ ~]$

Cool, en one shot ça donne donc :
LC_NUMERIC=fr_FR.UTF-8 gawk '/wlp2s0/{printf "%'"'"'dn", $10}' /proc/net/dev

Super ! Ça roxe !!
Et j'économise le passage par grep, rev et sed...
J'ai mis ça dans un script bash, donc wlp2s0 est dans une variable
INTERFACE, j'ai googlé pour trouver qu'on peut passer une variable à
gawk avec la syntaxe suivante :
LC_NUMERIC=fr_FR.UTF-8 gawk -v k=$INTERFACE 'if ($1==k){printf "%'"'"'dn", $10/1000}' /proc/net/dev
avec la subtilité que INTERFACE doit être égale à wlp2s0: (avec le ":")
J'ai encore une question à propos de la syntaxe...
Que signifie la chaine "%'"'"'d" ?
Ce qui est très étonnant pour moi, c'est le nombre impair de « ' »
Merci encore à vous deux !
Avatar
Nicolas George
Lulu , dans le message , a
écrit :
LC_NUMERIC=fr_FR.UTF-8 gawk -v k=$INTERFACE 'if ($1==k){printf "%'"'"'dn", $10/1000}' /proc/net/dev
Que signifie la chaine "%'"'"'d" ?

Rien du tout.
Ce qui est très étonnant pour moi, c'est le nombre impair de « ' »

Et c'est très juste. C'est parce qu'ils ne vont pas ensemble.
Le début, « "% », fait partie du script gawk.
Le ' termine la chaîne qui a commencé à « 'if »
Le « "'" » est une chaîne qui contient uniquement une apostrophe.
Le ' commence une chaîne qui se terminera avant /proc/net/dev.
La fin, « dn" », fait partie du script.
Il faut se rappeler que dans une chaîne entre ', seul ' est actif pour
marquer la fin de la chaîne, il n'y a pas d'échappement. Donc il est
impossible de faire figurer ' lui-même.
À la place, on assemble une chaîne entre ' puis une apostrophe seule
entre " puis une chaîne entre ' pour la fin du script. C'est pénible,
mais moins que de devoir penser à quoter tous caractères spéciaux pour
une chaîne en ".
Tout ceci se passe au niveau du shell. Ce que gawk voit, c'est :
« if ($1==k){printf "%'dn", $10/1000} » (avec des guillemets français
pour délimiter).
Avatar
Benoit Izac
Bonjour,
Le 30/03/2020 à 16:48, Lulu a écrit dans le message
 :
J'ai mis ça dans un script bash, donc wlp2s0 est dans une variable
INTERFACE, j'ai googlé pour trouver qu'on peut passer une variable à
gawk avec la syntaxe suivante :
LC_NUMERIC=fr_FR.UTF-8 gawk -v k=$INTERFACE 'if ($1==k){printf
"%'"'"'dn", $10/1000}' /proc/net/dev
avec la subtilité que INTERFACE doit être égale à wlp2s0: (avec le ":")

Tu peux faire « '$1==k":" {…}' »
--
Benoit Izac
Avatar
Lulu
Le 30-03-2020, Nicolas George <nicolas$ a écrit :
Lulu , dans le message , a
écrit :
LC_NUMERIC=fr_FR.UTF-8 gawk -v k=$INTERFACE 'if ($1==k){printf "%'"'"'dn", $10/1000}' /proc/net/dev

Que signifie la chaine "%'"'"'d" ?

Rien du tout.
Ce qui est très étonnant pour moi, c'est le nombre impair de « ' »

Et c'est très juste. C'est parce qu'ils ne vont pas ensemble.
Le début, « "% », fait partie du script gawk.
Le ' termine la chaîne qui a commencé à « 'if »
Le « "'" » est une chaîne qui contient uniquement une apostrophe.
Le ' commence une chaîne qui se terminera avant /proc/net/dev.

0K
La fin, « dn" », fait partie du script.
Il faut se rappeler que dans une chaîne entre ', seul ' est actif pour
marquer la fin de la chaîne, il n'y a pas d'échappement. Donc il est
impossible de faire figurer ' lui-même.

0K
À la place, on assemble une chaîne entre ' puis une apostrophe seule
entre " puis une chaîne entre ' pour la fin du script. C'est pénible,
mais moins que de devoir penser à quoter tous caractères spéciaux pour
une chaîne en ".
Tout ceci se passe au niveau du shell. Ce que gawk voit, c'est :
« if ($1==k){printf "%'dn", $10/1000} » (avec des guillemets français
pour délimiter).

Mais quel est l'intéret de passer une apostrophe ' au shell entre les
deux «commandes» gawk 'if ($1==k){printf "%' et 'dn", $10/1000}' /proc/net/dev
Cette "gymnastique" m'échappe complètement et me rend gawk complètement
obscur alors que je sens bien la puissance du machin.
(« Sans maîtrise, la puissance n'est rien » ©Pirelli ;-)
Avatar
Lulu
Le 30-03-2020, Benoit Izac a écrit :
Le 30/03/2020 à 16:48, Lulu a écrit dans le message
J'ai mis ça dans un script bash, donc wlp2s0 est dans une variable
INTERFACE, j'ai googlé pour trouver qu'on peut passer une variable à
gawk avec la syntaxe suivante :
LC_NUMERIC=fr_FR.UTF-8 gawk -v k=$INTERFACE 'if ($1==k){printf
"%'"'"'dn", $10/1000}' /proc/net/dev
avec la subtilité que INTERFACE doit être égale à wlp2s0: (avec le ":")

Tu peux faire « if ($1==k":") {…} »

0K. Merci encore.
Avatar
Benoit Izac
Bonjour,
Le 31/03/2020 à 20:11, Lulu a écrit dans le message
 :
Tout ceci se passe au niveau du shell. Ce que gawk voit, c'est :
« if ($1==k){printf "%'dn", $10/1000} » (avec des guillemets français
pour délimiter).

Mais quel est l'intéret de passer une apostrophe ' au shell entre les
deux «commandes» gawk 'if ($1==k){printf "%' et 'dn", $10/1000}' /proc/net/dev

Il n'est pas question de passer deux commandes à gawk mais de lui passer le
« %'d » pour qu'il formate correctement le nombre. Comme « ' » est
utilisé pour marquer le début et la fin de la commande gawk, on ne peut
pas utiliser « ' » simplement.
Le problème n'a donc rien à voir avec awk mais vient du shell qui
supprime les « ' » qui marquent le début fin de chaînes. Imaginons que
tu veuilles afficher « _'_ » dans la console, tout en utilisant « ' »
comme début/fin de chaîne, il y a plusieurs possibilités :
$ printf '%sn' '_'"'"'_' # encadrer le « ' » dans des « " »
$ printf '%sn' '_'''_' # échapper le « ' » avec «  »
Ou encore utiliser une extension bash qui permet d'interpréter le «  »
dans une chaîne :
$ printf '%sn' $'_'_'
$ printf '%sn' $'_47_'
--
Benoit Izac
Avatar
Lulu
Le 31-03-2020, Benoit Izac a écrit :
Le 31/03/2020 à 20:11, Lulu a écrit dans le message
Tout ceci se passe au niveau du shell. Ce que gawk voit, c'est :
« if ($1==k){printf "%'dn", $10/1000} » (avec des guillemets français
pour délimiter).

Mais quel est l'intéret de passer une apostrophe ' au shell entre les
deux «commandes» gawk 'if ($1==k){printf "%' et 'dn", $10/1000}' /proc/net/dev

Il n'est pas question de passer deux commandes à gawk mais de lui
passer le « %'d » pour qu'il formate correctement le nombre. Comme
« ' » est utilisé pour marquer le début et la fin de la commande
gawk, on ne peut pas utiliser « ' » simplement.
Le problème n'a donc rien à voir avec awk mais vient du shell qui
supprime les « ' » qui marquent le début fin de chaînes. Imaginons
que tu veuilles afficher « _'_ » dans la console, tout en utilisant
« ' » comme début/fin de chaîne, il y a plusieurs possibilités :
$ printf '%sn' '_'"'"'_' # encadrer le « ' » dans des « " »
$ printf '%sn' '_'''_' # échapper le « ' » avec «  »
Ou encore utiliser une extension bash qui permet d'interpréter le «  »
dans une chaîne :
$ printf '%sn' $'_'_'
$ printf '%sn' $'_47_'

Pfff...
Je n'aurais jamais trouvé ça tout seul...
Merci pour la leçon ;-)