Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 13/07/2009, à 12:42

Solaris974

Questions sur AWK

Bonjour,
Je dois parcourir avec AWK un fichier du style :

nom.prenom:         nomprenom
nom2.prenom2:       nom2prenom2@un.exemple.com

J'utilise cette commande pour séparer les 2 champs :

awk -F ':' '{print $1 " " $2}' aliases

# ce qui donne :

nom.prenom 			nomprenom
nom2.prenom2 	nom2prenom2@un.exemple.com

Donc premièrement j'aimerais savoir s'il y a une option pour ignorer tous les espaces ?
Deuxièmement je cherche si c'est possible de commencer à partir d'une ligne qui commence par "# Person who should get..."

Et éventuellement comment faire une confition IF ... ELSE sur chaque retour de la variable $2 si le champs contient "@un.exemple.com" ou pas

merci beaucoup wink


« La Terre est le berceau de l'humanité... Mais passe-t-on sa vie entière dans un berceau ? »

Quad-core i5 3,4Ghz  / 16Go DDR3  /  nVidia GTX 660 2Go OC  /  SSD OCZ Agility 4 256Go

Hors ligne

#2 Le 13/07/2009, à 18:01

claudius01

Re : Questions sur AWK

Bonjour,

Une première passe consisterait à remplacer tous les espaces consécutifs par un seul pour une meilleure présentation. Je te propose :

 ... | awk '{for (n = 0; n < NF; n++) { printf("%s ", $(1+n));} printf("\n"); }'

Par contre, si tu veux supprimer tous les espaces (cela ne sera plus le séparateur de présentation)

... | sed 's/ //g'

Quant à détecter un pattern du type "# Person ..."

 ... | awk '{ if ($0 ~ /^# Person/) { printf("Bingo [%s]\n", $0); } }'

Maintenant, il faut mettre tout cela dans un script awk car le travail en pipe a ses limites

 ... | awk -F ':'  '
  BEGIN {
   ...
  }
  {
   ...
  }
  END {
  ...
  }
'

Cordialement, A+
--
Claudius

Hors ligne

#3 Le 13/07/2009, à 23:27

Totor

Re : Questions sur AWK

Bonsoir,

Solaris974 a écrit :

Donc premièrement j'aimerais savoir s'il y a une option pour ignorer tous les espaces ?

Non, il n'y a pas d'option à cet effet. Cependant, le résultat souhaité peu être obtenu d'au moins 2 façons :
1. En rusant avec la variable FS

awk '{FS=" ";$0=$1""$2;FS=":";print $1 " " $2}' aliases

2. En supprimant les espaces via gsub

awk -F":" '{ gsub(/:[[:blank:]]+/,":"); print $1 " " $2}' aliases

La 2nde solution n'est pas posix et ne fonctionne qu'avec gawk.

Solaris974 a écrit :

Deuxièmement je cherche si c'est possible de commencer à partir d'une ligne qui commence par " ..."

Avec awk, il te faut positionner un indicateur :

awk -F":" ' /^# Person who should get*/ {debut=1} debut==1 {<ton traitement>}' aliases

Solaris974 a écrit :

Et éventuellement comment faire une confition IF ... ELSE sur chaque retour de la variable $2 si le champs contient "@un.exemple.com" ou pas

Voici :

awk -F":" ' /^# Person who should get*/ {debut=1} debut==1 {if ($2 ~ /@un\.exemple\.com$/) { <traitement condition ok> } else {<traitement condition ko>} } ' aliases

Donc au final :

awk -F":" ' {gsub(/:[[:blank:]]+/,":")} /^# Person who should get*/ {debut=1} debut==1 {if ($2 ~ /@un\.exemple\.com$/) { <traitement condition ok> } else {<traitement condition ko>} }' aliases

Voilà, je n'ai pas testé car pas de linux sous la main ! mais ça devrait être bon.


-- Lucid Lynx --

Hors ligne

#4 Le 15/07/2009, à 09:12

Solaris974

Re : Questions sur AWK

Merci beaucoup Totor et claudius01, je comprends un peu mieux Awk maintenant, j'ai aussi trouver une doc.
J'estime être assez bon en ScriptingBash mais Awk et Sed pour le moment c'est autre chose...

Donc ce que vous me montrer fonctionne mais il y a encore une ou deux chose qui bloc un peu.

- Il me semble que la commande gsub(/:[[:blank:]]+/,":") ne fonctionne pas car se sont apparemment des tabulations dans le fichier.

- et pour commencer awk à partir de la ligne « # Person who should get root's mail » ca ne fonctionne pas non plus même si l'indicateur en lui même marche.
(au passage comment faire pour ne pas interpréter l'apostrophe « ' » dans un chaine de caractère dans Awk ? merci)



Maintenant pour avancer un peu plus dans mon script, j'aimerais utiliser une fonction pour éviter de surcharger le tout, comme ceci :

#!/bin/sh

function nompre(abc) {
awk -F '.' '{print "INSERT INTO aliases VALUES ("$1, $2")" >> fichier}' abc
};

awk -F ":" ' {gsub(/:[[:blank:]]+/,":")} /^# Person who should get*/ {debut=1} debut==1 {if ($2 ~ /@un\.exemple\.com$/) { print "OK" } else { nompre($1) } }' aliases

Mais j'obtiens toujours cette erreur et je ne vois pas ce qu'il y a comme problème..
Voici l'erreur :

MAIL.sh: line 3: Erreur de syntaxe près du symbole inattendu « abc »
MAIL.sh: line 3: `function nompre(abc) {'

Merci


« La Terre est le berceau de l'humanité... Mais passe-t-on sa vie entière dans un berceau ? »

Quad-core i5 3,4Ghz  / 16Go DDR3  /  nVidia GTX 660 2Go OC  /  SSD OCZ Agility 4 256Go

Hors ligne

#5 Le 15/07/2009, à 10:37

claudius01

Re : Questions sur AWK

Bonjour,

Es-tu conscient que dans le code

#!/bin/sh

function nompre(abc) {
awk -F '.' '{print "INSERT INTO aliases VALUES ("$1, $2")" >> fichier}' abc
};

awk -F ":" ' {gsub(/:[[:blank:]]+/,":")} /^# Person who should get*/ {debut=1} debut==1 {if ($2 ~ /@un\.exemple\.com$/) { print "OK" } else { nompre($1) } }' aliases

La déclaration de 'function nompre(abc)' est une fonction du script .sh alors que manifestement tu souhaites qu'elle soit une fonction de awk; fonction qui elle-même appelle ... awk

Si je puis me permettre, essaie d'utiliser un et un seul awk comme ci-après et avec la définition d'une fonction telle que tu le désires (enfin, sauf erreur de ma part)

... | awk -F ':'  '
  BEGIN {
      ...
  }
  function nompre(abc) {
      ...
  }
  {
      ...
  }
  END {
      ...
  }
'

Il faut voir awk comme un super filtre qui est un programme avec sa propre syntaxe malheureusement proche des autres langages comme ksh, sh, C, etc. qui prend un flux en entrée (stdin ou fichier) et le ressort en sortie (stdout ou fichier).

Cordialement, A+
--
Claudius

Hors ligne

#6 Le 15/07/2009, à 10:41

Totor

Re : Questions sur AWK

Solaris974 a écrit :

- Il me semble que la commande gsub(/:[[:blank:]]+/,":") ne fonctionne pas car se sont apparemment des tabulations dans le fichier.

J'ai justement mis "blank" pour inclure les tabulations. Mais tu peux remplacer par "space", d'autres caractères composent cette classe de caractères.
Note : ça fonctionne très bien chez moi.

Solaris974 a écrit :

- et pour commencer awk à partir de la ligne « # Person who should get root's mail » ca ne fonctionne pas non plus même si l'indicateur en lui même marche.
(au passage comment faire pour ne pas interpréter l'apostrophe « ' » dans un chaine de caractère dans Awk ? merci)

Qu'est-ce qui ne fonctionne pas ?
Certe, awk lira ton fichier depuis le début mais avec l'indicateur, il commencera ton traitement uniquement si debut=1.
Note : ça fonctionne très bien chez moi. J'ai juste rajouté un ;next après debut=1 pour éviter qu'il ne traite la ligne # Personwho should get...

/^[[:blank:]]*# Person who should get / {debut=1;next}

Solaris974 a écrit :

(au passage comment faire pour ne pas interpréter l'apostrophe « ' » dans un chaine de caractère dans Awk ? merci)

awk -F ":" ' {gsub(/:[[:blank:]]+/,":")} /^[[:blank:]]*# Person who should get root'"'"'s mail/ {debut=1;next} debut==1 {print}' aliases
Solaris974 a écrit :
#!/bin/sh

function nompre(abc) {
awk -F '.' '{print "INSERT INTO aliases VALUES ("$1, $2")" >> fichier}' abc
};

awk -F ":" ' {gsub(/:[[:blank:]]+/,":")} /^# Person who should get*/ {debut=1} debut==1 {if ($2 ~ /@un\.exemple\.com$/) { print "OK" } else { nompre($1) } }' aliases

La définition de fonction awk doit s'effectuer dans le corps du script awk et non dans le corps du script sh !


-- Lucid Lynx --

Hors ligne

#7 Le 15/07/2009, à 15:35

Solaris974

Re : Questions sur AWK

Alors j'ai réussi à faire un début fonctionnel en modifiant certaines choses:

awk -F ' ' '{gsub(":","")} /# Person who should get root'"'"'s mail*/ {debut=1;next} debut==1 {print}' /etc/mail/aliases

J'ai remplacé   awk -F ':' ...  par  awk -F ' ' ...
et gsub(/:[[:blank:]]+/,":")   par  gsub(":","")

Pour  /^[[:blank:]]*# Person who should get root'"'"'s mail/ {debut=1;next} debut==1
j'ai remplacé par   /# Person who should get root'"'"'s mail/ {debut=1; next} debut==1

Parcontre dès que je remplace  {print}  par une condition  {if ($2 ~ /@un\.exemple\.com$/) { print } else { print } }  ..ca ne fonctionne plus, il reparcourt tout le fichier.


----------------------------------------------------------

Encore une ptite question.

Si je fais cette commande :

awk -F ' ' ' 
function nompre(champ1, champ2) { awk -F ''.'' ''{print "Prenom : "$1"Nom : "$2")"}'' champ1 }
{gsub(":","")}
/# Person who should get*/ {debut=1; next} debut==1 
{if ($2 ~ /@un\.exemple\.com$/) { print "OK" } else { nompre($1,$2) } }' /etc/mail/aliases

J'ai cette erreur :
awk: 2: unexpected character '.'
awk: line 2: syntax error at or near }

Est ce bien comme cela qu'il faut déclarer une fonction qui utilise awk dans awk ? avec des doubles apostrophes ?

Dernière modification par Solaris974 (Le 15/07/2009, à 15:39)


« La Terre est le berceau de l'humanité... Mais passe-t-on sa vie entière dans un berceau ? »

Quad-core i5 3,4Ghz  / 16Go DDR3  /  nVidia GTX 660 2Go OC  /  SSD OCZ Agility 4 256Go

Hors ligne

#8 Le 15/07/2009, à 21:32

Totor

Re : Questions sur AWK

Est-ce possible d'avoir un échantillon du dit fichier aliases ? quelques lignes avant le # Person who should get root's mail et quelques lignes après ?
(par un copier/coller pour conserver le format)
si les données sont trop "sensibles", modifies les valeurs mais ne change pas le format


-- Lucid Lynx --

Hors ligne

#9 Le 16/07/2009, à 06:54

Solaris974

Re : Questions sur AWK

Voilà, mais les tabulations ne reste pas parcontre

ntp:		root
mysql:		root
desktop:	root
rpcuser:	root
rpc:		root
nfsnobody:	root

ingres:		root
system:		root
toor:		root
manager:	root
dumper:		root
abuse:		root

newsadm:	news
newsadmin:	news
usenet:		news
ftpadm:		ftp
ftpadmin:	ftp
ftp-adm:	ftp
ftp-admin:	ftp
www:		root
#webmaster:	root
noc:		root
security:	root
hostmaster:	root
info:		postmaster
marketing:	postmaster
sales:		postmaster
support:	postmaster


# trap decode to catch security attacks
decode:		root

# Person who should get root's mail
root:						jim.eeeee
administrateur-messagerie:		jim.eeeee
#abuse:					abuse
#
backuppc:				jim.eeeee,jef,jim.eeeee@oooooo.fr
#
exemple:				exemple
#
anissa.hhhhh:			ahdgqs
bruno.hhhhh:			bhqrgeq
#claudine.aaaaazot:			caqerge
philibert.cccccc:			pcqerge
claudine.cccooog:			ceresr
christian.fffff:			cfgejt
carole.fffffff:			cfrjhjh
christine.ffff:			chfdhjfr
carole.lllll:			cluomur
chantal.sssss:			csfjdd
chantale.ssssss:			cserjyn
cindy.xxxxx:			cxbwde

« La Terre est le berceau de l'humanité... Mais passe-t-on sa vie entière dans un berceau ? »

Quad-core i5 3,4Ghz  / 16Go DDR3  /  nVidia GTX 660 2Go OC  /  SSD OCZ Agility 4 256Go

Hors ligne

#10 Le 16/07/2009, à 09:30

Totor

Re : Questions sur AWK

J'ai remplacé les espaces par 2 tabulations à la ligne "backuppc". Je n'ai rien changé à mon script :

>awk -F ":" ' {gsub(/:[[:blank:]]+/,":")} /^[[:blank:]]*# Person who should get root'"'"'s mail/ {debut=1;next} debut==1 {if ($2 ~ /@oooooo\.fr$/) { print } else print "beeeurk" }' aliases
beeeurk
beeeurk
beeeurk
beeeurk
backuppc:jim.eeeee,jef,jim.eeeee@oooooo.fr
beeeurk
beeeurk
beeeurk
beeeurk
beeeurk
beeeurk
beeeurk
beeeurk
beeeurk
beeeurk
beeeurk
beeeurk
beeeurk
beeeurk
beeeurk

Pour ta fonction nompre :

awk 'function nompre(valeur) {FS="."; split(valeur,champs);print "INSERT INTO aliases VALUES (\""champs[1]"\", \""champs[2]"\");" >> "tonFichierInsert"} {FS=":";gsub(/:[[:blank:]]+/,":")} /^[[:blank:]]*# Person who should get root'"'"'s mail/ {debut=1;next} debut==1 {if ($2 ~ /@oooooo\.fr$/) { print } else nompre($1) }' aliases

je te laisse le finaliser (notament pour filtrer les commentaires)

Dernière modification par Totor (Le 16/07/2009, à 18:06)


-- Lucid Lynx --

Hors ligne

#11 Le 16/07/2009, à 11:35

aleph2

Re : Questions sur AWK

Un peu hors-sujet, mais...

j'aime bien ce forum, c'est une mine d'or inépuisable pour tester mon interpréteur interactif.

>>> s = """\
info:        postmaster
marketing:    postmaster
sales:        postmaster
support:    postmaster


# trap decode to catch security attacks
decode:        root

# Person who should get root's mail
root:                        jim.eeeee
administrateur-messagerie:        jim.eeeee
#abuse:                    abuse
#
backuppc:                jim.eeeee,jef,jim.eeeee@oooooo.fr
#
exemple:                exemple
#
anissa.hhhhh:            ahdgqs
bruno.hhhhh:            bhqrgeq
#claudine.aaaaazot:            caqerge
philibert.cccccc:            pcqerge
"""
>>> r = s.split('\n')
>>> i = r.index("# Person who should get root's mail")
>>> r2 = r[i + 1:]
>>> r3 = [e for e in r2 if e]
>>> r4 = [e for e in r3 if not e.startswith('#')]
>>> r5 = [e.split() for e in r4]
>>> for e in r5:
        print '%-40s%-40s %s' % (e[0], e[1], '@' in e[1])
        
root:                                   jim.eeeee                                False
administrateur-messagerie:              jim.eeeee                                False
backuppc:                               jim.eeeee,jef,jim.eeeee@oooooo.fr        True
exemple:                                exemple                                  False
anissa.hhhhh:                           ahdgqs                                   False
bruno.hhhhh:                            bhqrgeq                                  False
philibert.cccccc:                       pcqerge                                  False
>>>

#12 Le 16/07/2009, à 20:18

Solaris974

Re : Questions sur AWK

CA Y EST !!!

j'y suis arrivé! tongue

Le voilà mon magnifique script :

#!/bin/sh

awk -F ' ' '{gsub(":","")}

{ if ($2 ~ /@un\.exemple\.com$/ || /#/) { print "  OK   " $1" --- "$2 }
	else { 
		{if ( $0 == "" || $1 == "root" || $2 == "root" || $2 == "ftp" || $2 == "postmaster" || $2 == "news")
		{ }
		else {print "INSERT " $1" --- "$2; print $1 > "awk_prenom-nom"} }
	}
}' /etc/mail/aliases


awk -F '.' '{if (length($1)<7) { print "Prénom : "$1"\t\tNom : "$2 } else { print "Prénom : "$1"\tNom : "$2} }
{if (!$2) { print $1 > "prenom-nom" } else { print $1" ."$2" " substr($2,1,1) > "prenom-nom"} }' awk_prenom-nom


awk -F ' ' '{print "INSERT INTO mail.alias (address, goto, domain, created, modified, active) VALUES ('"'"'"$1$2"@un.exemple.com'"'"','"'"'"$1$3"@exemple.com'"'"','"'"'un.exemple.com'"'"',NOW(),NOW(),'"'"'1'"'"');\nINSERT INTO mail.alias (address, goto, domain, created, modified, active) VALUES ('"'"'"$1$2"@exemple.com'"'"','"'"'"$1$3"@exemple.com'"'"','"'"'exemple.com'"'"',NOW(),NOW(),'"'"'1'"'"');"}
{print "INSERT INTO mail.alias (address, goto, domain, created, modified, active) VALUES ('"'"'"$1$2"@un.exemple.com'"'"','"'"'"$1$3"@exemple.com'"'"','"'"'un.exemple.com'"'"',NOW(),NOW(),'"'"'1'"'"');\nINSERT INTO mail.alias (address, goto, domain, created, modified, active) VALUES ('"'"'"$1$2"@exemple.com'"'"','"'"'"$1$3"@exemple.com'"'"','"'"'exemple.com'"'"',NOW(),NOW(),'"'"'1'"'"');" > "alias.sql"}' prenom-nom

Tout ca pas mal grâce à vous, merci encore!

Comme j'ai pas du tout réussi à faire fonctionner  {debut=1} debut==1  j'ai remplacé par ca (qui est finalement plus approprié) :

... {if ( $0 == "" || $1 == "root" || $2 == "root" || $2 == "ftp" || $2 == "postmaster" || $2 == "news") ...

Maintenant il ne reste plus qu'à insérer une condition en SQL pour ne pas insérer la ligne si elle existe déjà cool
et continuer pour les autres tables.

Je comprends largement mieux AWK maintenant !
Merci encore !

Dernière modification par Solaris974 (Le 16/07/2009, à 20:21)


« La Terre est le berceau de l'humanité... Mais passe-t-on sa vie entière dans un berceau ? »

Quad-core i5 3,4Ghz  / 16Go DDR3  /  nVidia GTX 660 2Go OC  /  SSD OCZ Agility 4 256Go

Hors ligne

#13 Le 17/07/2009, à 13:25

obibann

Re : Questions sur AWK

cat monfichier | tr -s " " ":" | tr -s ":" ";" | awk 'BEGIN{FS=";"}{print $1" "$2}'

Dernière modification par obibann (Le 17/07/2009, à 13:30)


Ubuntu 16.04
Avec Windows, on fait ce qu'on peut... Avec Linux, on fait ce qu'on veut !! :p

Hors ligne