Richard Bruno
navigation
Home
admin









Awk
October 18th, 2016

Table des matières


Variables prédéfinies
Infos diverses
Compter les occurrences des IPs dans un fichier de log
Calculer la taille occupée par plusieurs File Systems
Extraire les subjects de mails stockés dans un fichier au format mime
Exercice : Analyse d'un fichier au format MIME
Exercice : Modifications de fichiers de config

Variables prédéfinies


Par exemple,
$NR : le nombre total de lignes du fichiers

cf. http://www.shellunix.com/awk.html#var_predef


Lancement


fichier_awk : fichier contenant les commandes awk
fichier_data : fichier contenant les données à analyser

awk -f fichier_awk fichier_data


Infos diverses


Commentaire : "tout ce qui est entre # et la fin de la ligne est ignoré par awk"
substr(s,i,n), retourne la sous chaine de s commencant en i et de taille n
Insérer des variables du shell dans une commande awk :

#!/bin/bash
$rep="/toto"
$liste="/toto/fichier_liste"
cat $liste |awk -v rep=$rep '{print $1" trouvé dans repertoire "rep}'


On notera :
- le "-v" en début de awk qui affecte la variable
- le fait que les variables dans le awk n'ont pas de $
- si on veut affecter plusieurs variables, on ajoutera autant de "-v"

Source : http://www.commentcamarche.net/forum/affich-1006695-awk-et-variables

Modifier une chaine :

[...]|awk '{sub(/\..0/,"",$4);print $4}'


On supprime de la chaine $4, les caractères ".[n'importe quel caractère]0"

Source : http://people.cs.uu.nl/piet/docs/nawk/nawk_92.html

Insérer un quote dans la sortie du awk

Il faut insérer le code \x27 :

echo quote | awk '{print $1" : \x27"}'



Source : http://www.unix.com/shell-programming-scripting/44875-inserting-apostrophe-into-awk-output.html


Compter les occurrences des IPs dans un fichier de log


Exemple de logs :

1.1.1.1 - - [16/Jul/2011:16:48:48 +0200] "GET /index.jsp HTTP/1.1" 302 5863 "http://www" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30"
1.1.1.1 - - [16/Jul/2011:16:48:48 +0200] "GET /login?service=http%3A%2F%2Fuwww%2Flogin%2Findex.php&gateway=true HTTP/1.1" 302 37 "-" "-"
1.1.1.2 - - [16/Jul/2011:16:48:48 +0200] "GET /login?service=http://www/Login HTTP/1.1" 200 2388 "http://www/render.userLayoutRootNode.uP" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30"



Le script awk :

BEGIN { }
{
ip_courante=$1;
#print "ip_courante : "ip_courante;
occ=tableau_ip[ip_courante];
#print "nb occurrences : "occ;
occ2=occ+1;
#print "nb occurrences : "occ2;
tableau_ip[ip_courante]=occ2;

}
END {

for (ip_courante in tableau_ip)
{ print ip_courante " " tableau_ip[ip_courante]
}


}



Lancement et tri :

awk -f script_awk fichier_de_logs |sort -g -k 2


Ne pas oublier le "-g" => on compare des valeurs numériques

Résultat :

1.1.1.2 1
1.1.1.1 2



Calculer la taille occupée par plusieurs File Systems



df -lP |egrep -v 'sapdata|mirrlog|oraarch|saprorg|origlog|tmpfs|sapreorg|Filesys'|awk '{total+=$3}END{print total}'


En plus condensé :


df -lP |awk '!/sapdata|mirrlog|oraarch|saprorg|origlog|tmpfs|sapreorg|Filesys/ {total+=$3}END{print total}'



Extraire les subjects de mails stockés dans un fichier au format mime


Nous avons un fichier au format mime :


[...]
Subject: ici un sujet
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha1; boundary="------------ms020403060404040103030605"
[...]


qui peut être sur deux lignes


[...]
Subject: ici
un sujet
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha1; boundary="------------ms020403060404040103030605"
[...]


Le fichier mime peut contenir plusieurs mails.
Version 1
Le script ci-dessous extrait tous les sujets.

$ cat /home/bruno/system/mails_to_fiesta_awk2
BEGIN {find=0}
{if (find==1) {find=0;if ($0 !~ /Content-Type:/) {print s$0;} else {print s} } }
/^Subject:/ {find=1;s=substr($0,10);}


Version 2
Le script ci-dessous extrait le nième sujet, n étant passé en paramètre.

$ cat /home/bruno/system/mails_to_fiesta_awk3
BEGIN {find=0;n=0}
{ if (find==1)
{
find=0;
if (n==l)
{
if ($0 !~ /Content-Type:/) {print s$0;}
else {print s}
}
}
}
/^Subject:/ {find=1;n++;s=substr($0,10);}


Avec un lancement de la forme :

awk -v l=4 -f system/mails_to_fiesta_awk3 mails/boite



Note L'extraction des corps des mails se fait très facilement avec mha-decode.

Exercice : Analyse d'un fichier au format MIME



Vous disposez d'un fichier au format MIME.
Exemple de fichier :

# cat fichier
From - Fri Jun 1 15:05:43 2012
X-Mozilla-Status: 0001
X-Mozilla-Status2: 00000000
Return-Path: <xxxxxxxxx>
X-Original-To: bruno.richard@univ-lemans.fr
Delivered-To: bruno.richard@univ-lemans.fr
Received: by xxxxx
X-Spam-Level:
X-Spam-Status: No, score=-6.9 required=6.0 tests=BAYES_00,UNIV_PHISH_TAG20,
UNIV_PHISH_TAG33 autolearn=ham version=3.3.1
Received: from localhost xxxx
Message-ID: xxx
Date: Fri, 01 Jun 2012 11:59:24 +0200
From: xxx
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20120428 Thunderbird/12.0.1
MIME-Version: 1.0
To: xxx
Subject: xxx
X-Enigmail-Version: 1.4.1
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha1; boundary="------------ms050001040609010406060507"
X-Validation-by: certsvp@renater.fr

--------------ms050001040609010406060507
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

ici le corps du message
--------------ms050001040609010406060507
From - Fri Jun 1 15:05:43 2012
X-Mozilla-Status: 0001
X-Mozilla-Status2: 00000000
Return-Path: <xxxxxxxxx>
X-Original-To: bruno.richard@univ-lemans.fr
Delivered-To: bruno.richard@univ-lemans.fr
Received: by xxxxx
X-Spam-Level:
X-Spam-Status: No, score=-6.9 required=6.0 tests=BAYES_00,UNIV_PHISH_TAG20,
UNIV_PHISH_TAG33 autolearn=ham version=3.3.1
Received: from localhost xxxx
Message-ID: xxx
Date: Fri, 01 Jun 2012 11:59:24 +0200
From: xxx
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20120428 Thunderbird/12.0.1
MIME-Version: 1.0
To: xxx
Subject: xxx
X-Enigmail-Version: 1.4.1
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha1; boundary="------------ms050001040609010406060507"
X-Validation-by: certsvp@renater.fr

--------------ms050001040609010406060507
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

ici le corps du message
--------------ms050001040609010406060507



Les messages peuvent ainsi s'enchainer au coeur d'un même fichier.
Exercice 1
Vous devez créer x fichiers, triés en fonction de la date du mail (!= ordre dans le fichier),
contenant en première ligne le sujet du mail, suivi du corps du mail.

Correction :

$ cat /home/bruno/system/mails_to_fiesta_awk4
BEGIN {find_body=0;find_subj=0;n=0;debut=0;find_bound=0}
/^Date:/ { d=$0;

an=substr(d,19,4);
mois=substr(d,15,3);
if (mois=="Jan") {mois="01";}
if (mois=="Feb") {mois="02";}
if (mois=="Mar") {mois="03";}
if (mois=="Apr") {mois="04";}
if (mois=="May") {mois="05";}
if (mois=="Jun") {mois="06";}
if (mois=="Jui") {mois="07";}
if (mois=="Aou") {mois="08";}
if (mois=="Sep") {mois="09";}
if (mois=="Oct") {mois="10";}
if (mois=="Nov") {mois="11";}
if (mois=="Dec") {mois="12";}
jour=substr(d,12,2);
heure=substr(d,24,8);
d2=an""mois""jour""heure;
#print n" "d2;
tab_date[n]=d2;


}
{ if (find_subj==1)
{

find_subj=0;
if ($0 ~ /^ /) {tab_subj[n]=s$0}
else {tab_subj[n]=s}


}
}
/^Subject:/ {find_subj=1;s=substr($0,10);}
{ if (find_bound==1)
{

if ($0 ~ b)
{


# on a trouvé un boundary
if (debut==1)
{

# on a trouvé le boundary de fin
debut=0;find_bound=0;
n++


}
else
{

# on a trouvé le boundary de debut
debut=1;


}
}
else
{

if (debut==1 && $0 !~ /Content-Type:/ && $0 !~ /Content-Transfer-Encoding/)
{
tab_body[n]=tab_body[n]"n"$0
}


}


}
}
/^Content-Type:.*boundary/ {find_bound=1;b=$0;gsub(/.*boundary="/,"",b);gsub(/"/,"",b);}
END {
isort(tab_date,tab_subj,tab_body,n);
for ( x = 1; x <= n; x++ ) {

print tab_date[x],tab_subj[x];
fichier_out="/home/bruno/mails_cert/awk_out/"x".txt"
print tab_subj[n] > fichier_out
print tab_body[n] >> fichier_out
close(fichier_out)


}
}

function isort( A,B,C, n,i, j, hold, hold2,hold3)
{

for( i = 2 ; i <= n ; i++)
{
hold = A[j = i]
hold2 = B[j = i]
hold3 = C[j = i]
while ( A[j-1] > hold)

{ j-- ; A[j+1] = A[j];B[j+1] = B[j];C[j+1] = C[j] }


A[j] = hold
B[j] = hold2
C[j] = hold3
}

}



Exercice 2
Vous devez créer x fichiers, ayant pour nom le sujet du mail et contenant le corps du mail.

$ cat /home/bruno/system/mails_to_fiesta_awk5
BEGIN {find_body=0;find_subj=0;n=0;debut=0;find_bound=0}
{ if (find_subj==1)

{
find_subj=0;
if ($0 ~ /^ /) {tab_subj[n]=s$0}
else {tab_subj[n]=s}
}


}
/^Subject:/ {find_subj=1;s=substr($0,10);}
{ if (find_bound==1)

{
if ($0 ~ b)
{


# on a trouvé un boundary
if (debut==1)
{


# on a trouvé le boundary de fin
debut=0;find_bound=0;
s=tab_subj[n];
gsub(/(/,"(",s);
gsub(/)/,")",s);
gsub(///," ",s);
gsub(" ","_",s);
fichier_out="/home/bruno/mails_cert/awk_out/"s".txt"
#print "écriture dans "fichier_out
print tab_body[n] > fichier_out
close(fichier_out)
n++


}
else
{


# on a trouvé le boundary de debut
debut=1;
}


}
else
{
if (debut==1 && $0 !~ /Content-Type:/ && $0 !~ /Content-Transfer-Encoding/)

{
tab_body[n]=tab_body[n]"n"$0
}


}


}


}
/^Content-Type:.*boundary/ {find_bound=1;b=$0;gsub(/.*boundary="/,"",b);gsub(/"/,"",b);}
END {
for ( x = 1; x <= n; x++ ) {

print tab_subj[x];


}
}



Extraction du sujet du mail

BEGIN {find_subject=0;boundary_set=0;boundary_en_cours_analyse=0;to_save=0;}
# gestion du titre
/Subject/ {if (find_subject==0) {find_subject=NR;subject_deb=$0} }
/^ / {if (find_subject!=0 && NR == find_subject+1) {subject_fin=$0;} }

END {subject=subject_deb" "subject_fin;gsub(/^Subject: /,"",subject);gsub(///,"_",subject);gsub(/ /,"_",subject);print subject}



Extraction du corps (type texte) du mail

BEGIN {boundary_set=0;boundary_en_cours_analyse=0;to_save=0;}

# recherche du boundary
# Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha1; boundary="------------ms07000400605000302"
/^Content-Type:.*boundary/ {boundary_set=1;dans_corps_message=0;trouve_corps_message=0;text_bound=0;boundary=$0;gsub(/.*boundary="/,"",boundary);gsub(/"/,"",boundary);}

# analyse des lignes contenant la borne
{ if (boundary_set==1)
{
# on a trouvé un boundary
# ------------ms07000400605000302
if ($0 ~ boundary)
{
boundary_en_cours_analyse=1;
message_texte=0;
to_save=0;
}
}
}

# type du message inclu dans la borne
# Content-Type: text/plain; charset=ISO-8859-1
#Content-Transfer-Encoding: quoted-printable
/Content-Type: / {
if ($0 ~ /Content-Type: text/)
{
if (boundary_en_cours_analyse==1)
{
message_texte=1;
}
}
}

# on a atteint la fin des définitions "Content-Type" du message inclu dans la borne
#Content-Type: text/plain; charset=ISO-8859-1
#Content-Transfer-Encoding: quoted-printable
/^ *$/ {
if (boundary_en_cours_analyse==1)
{
boundary_en_cours_analyse=0;
if (message_texte==1)
{
corps_message="";
to_save=1;
}
}
}

# extraction du corps du message
{ if (to_save==1)
{
# print $0;
corps_message=corps_message"n"$0;
}
}

END {gsub(/x3dx0a/,"",corps_message);print corps_message}




Exercice : Modifications de fichiers de config



Enoncé

Vous disposez de fichiers de la forme suivante :

more liste_sympa/config
visibility noconceal

review private

reply_to_header
apply forced
value sender

web_archive
access private

subject Enseignants du departement AB1

subscribe closed

serial 13

send privateoreditorkey

status open

shared_doc
d_edit private
d_read default

available_user_options
reception digest,digestplain,html,mail,nomail,not_me,notice,summary,txt,urlize

rfc2369_header_fields archive,help,owner,post,subscribe,unsubscribe

owner
reception mail
profile normal
email pierre.a@univ-lemans.fr

owner
reception mail
profile privileged
email marc.b@univ-lemans.fr

unsubscribe closed

creation

custom_subject SRC

bouncers_level1
rate 30
notification owner
action none

bouncers_level2
rate 75
notification owner
action remove_bouncers

verp_rate 100%



M Pierre A a un statut qualifié de "normal". Nous voulons qu'il soit maintenant "privileged".
Proposez un script faisant ces changements.

Une première solution

begin {trouve_owner = 0 ;trouve_pierre = 0;trouve_profile = 0}
$0 == "" {trouve_owner=0;trouve_pierre = 0;trouve_profile = 0}
$0 == "owner" {trouve_owner=1}
trouve_owner == 1 && $0 == "email pierre.a@univ-lemans.fr" {trouve_pierre = 1}
trouve_pierre == 1 && $0 ~ /profile/ {trouve_profile = 1}
trouve_profile == 0 {print $0}
trouve_profile == 1 {print "profile privileged";trouve_owner=0;trouve_pierre = 0;trouve_profile = 0}



Cette solution ne fonctionne que si la ligne "profile [...]" se trouve avant la chaine "email [...]"

Une solution qui fonctionne quel que soit l'ordre des paramètres

begin {trouve_owner = 0 ;trouve_pierre = 0;trouve_profile = 0;MEMO=""}
$0 == "" { if (trouve_owner == 1) {

if (trouve_pierre==1) {sub ("normal","privileged",MEMO)}
print MEMO;MEMO="";
trouve_owner=0;trouve_pierre = 0;trouve_profile = 0;
}
}


$0 ~ /^owner/ {trouve_owner=1;}
trouve_owner == 1 && $0 == "email pierre.a@univ-lemans.fr" {trouve_pierre = 1}
trouve_owner == 1 {MEMO=MEMO"n"$0}
trouve_owner == 0 {print $0}





Dernières modifs
VNC (November 22nd, 2020)
Editeurs (October 20th, 2016)
Awk (October 18th, 2016)
Claws Mail (October 18th, 2016)
Cups (October 18th, 2016)
Gimp (October 18th, 2016)
Git (October 18th, 2016)

Contact
Pour m'envoyer un mail,
Pour me laisser un commentaire :
richard.brunooo
chez
gmail.com


powered by kure, modified by Bruno