[Shell] grep - afficher que la première occurence trouvée?

grep - afficher que la première occurence trouvée? [Shell] - Codes et scripts - Linux et OS Alternatifs

Marsh Posté le 18-06-2003 à 11:06:43    

Salut,
 
En complément de spamassassin, qui est pour rappel un progamme qui filtre les spams et que j'ai réglé pour stocker les spams dans un répertoire nommé /var/spool/spam, j'ai écrit une petite ligne de commande qui extrait les lignes Subject des fichier stockés et les ajoute à un rapport (pour faciliter la vérification):
 
cat out.* | grep 'Subject:' > report.txt
 
le problème c'est que dans chaque fichier out. la ligne Subject: apparait 2 fois.
 
Comment faire donc pour n'écrire que la première occurence?
 
au passage, si quelqu'un sait comment faire pour ajouter le nom du fichier dans le rapport, je suis preneur...

Reply

Marsh Posté le 18-06-2003 à 11:06:43   

Reply

Marsh Posté le 18-06-2003 à 11:12:05    

(1) cat out.* | grep 'Subject' | tail -1 > report.txt
(2) for i in out.*; do echo -n "$i : " >> report.txt && cat $i | grep 'Subject' | tail -1 >> report.txt; done

Reply

Marsh Posté le 18-06-2003 à 11:15:10    

merci minusplus, la première commande ne me sors que l'occurence du dernier fichier...
 
mais la deuxième marche nickel :D
 
bien qu'elle soit un peu longue à éxecuter...


Message édité par duch le 18-06-2003 à 11:17:28
Reply

Marsh Posté le 18-06-2003 à 12:05:35    

Le cat ne sert à rien.
Il suffit de faire "grep chaine fichier" (et puis comme ça ça t'affichera le nom du fichier).
Si la ligne "Subject:" est identique, tu peux utiliser uniq pour la supprimer :
 
grep 'Subject:' out.* | uniq

Reply

Marsh Posté le 18-06-2003 à 12:07:02    

merci pour la précision pour uniq.
 
Le cat me sert car je crér un nouveau fichier qd même...

Reply

Marsh Posté le 18-06-2003 à 14:53:48    

duch a écrit :

Le cat me sert car je crér un nouveau fichier qd même...


 
oui, et ?  
 
sinon je pense que tu peux faire un
 
(grep 'Subject:' out.* | head -n 1) > report.txt


---------------
Self Destruction Might Be The Answer - http://www.kazekami.org
Reply

Marsh Posté le 18-06-2003 à 14:56:37    

KazeKami a écrit :


 
oui, et ?  
 
sinon je pense que tu peux faire un
 
(grep 'Subject:' out.* | head -n 1) > report.txt


 
EDIT: http://rhols66.adsl.netsonic.fi/era/unix/award.html


Message édité par houplaboom42 le 18-06-2003 à 15:02:14
Reply

Marsh Posté le 18-06-2003 à 14:57:21    


 
not found :/


---------------
Self Destruction Might Be The Answer - http://www.kazekami.org
Reply

Marsh Posté le 18-06-2003 à 15:01:50    

Reply

Marsh Posté le 18-06-2003 à 15:08:00    

KazeKami >
 
merci beacoup pour la précision, j'ai pô tout compris mais j'vais regardé :D
 
mais comment tu fais pour boucler sur tous les fichiers?


Message édité par duch le 18-06-2003 à 15:13:25
Reply

Marsh Posté le 18-06-2003 à 15:08:00   

Reply

Marsh Posté le 18-06-2003 à 15:17:38    

duch a écrit :

KazeKami >
 
merci beacoup pour la précision, j'ai pô tout compris mais j'vais regardé :D
 
mais comment tu fais pour boucler sur tous les fichiers?


 
effectivement je suis fatigué, j'ai pas fait attention que tu faisais ca sur out.* :mrgreen:
 
la solution de -/+ est bien en fait :whistle:


---------------
Self Destruction Might Be The Answer - http://www.kazekami.org
Reply

Marsh Posté le 18-06-2003 à 16:13:45    

arf! :p

Reply

Marsh Posté le 18-06-2003 à 17:19:19    

:sol:

Reply

Marsh Posté le 19-06-2003 à 10:27:39    

je vous mets une nouvelle fois à contribution pour améliorer un poil le script...
 
j'aimerais renommer tous les fichiers de la forme out.* en out.*.reported (ça je sais faire), mais ce que je ne sais pas faire c'est ignorer les fichiers du type out.*.reported lorsque je crée le rapport (le but est de les appeler .reported pour les ignorer le prochain coup)
 
j'ai essayé ça :
 

Code :
  1. for i in /var/spool/spam/out.* | grep -v reported; do echo -n "$i : " >> /var/spool/filter/report.txt && cat $i | grep 'Subject' | tail -1 >> /var/spool/filter/report.txt && cat $i | grep 'Content analysis details' >> /var/spool/filter/report.txt; done
  2. for i in /var/spool/spam/out.*; do mv $i $i.reported; done


 
la deuxième ligne qui renomme les fichiers marche évidemment mais il encaisse pas le grep dans la première...
 
il y a sans doute une syntaxe particulière dans le cas d'un for in mais j'la connais pô :(


Message édité par duch le 19-06-2003 à 10:29:08
Reply

Marsh Posté le 19-06-2003 à 10:51:10    

ça :


for i in /var/spool/spam/out.* | grep -v reported; do echo -n "$i : " >> /var/spool/filter/report.txt


ça va pas. ce que tu veux faire, c'est ça :


for i in $(ls /var/spool/spam/out.* | grep -v reported); do echo -n "$i : " >> /var/spool/filter/report.txt


mais c'est moche. Dans ton cas vaut mieux utiliser find :


find -name "out.*" ! -name "*.reported" -exec echo "{} :" >> /var/spool/filter/report.txt && cat "{}" | grep Subject | head -1 >> /var/spool/filter/report.txt && mv "{}" "{}".reported \;  

Reply

Marsh Posté le 19-06-2003 à 10:52:43    

ou plus court :


find -name "out.*" ! -name "*.reported" -exec echo "{} : $(cat {} | grep Subject | head -1 )" >> /var/spool/filter/report.txt && mv "{}" "{}".reported \;  


 
 
 
tout ceci est à tester, hein ! :D

Reply

Marsh Posté le 19-06-2003 à 10:55:29    

arf
 
j'étais pas très loin, même si c'était moche :D
 
j'vais tester...
 
j'avais aussi ajouter ces 2 lignes ensuite mais j'suppose qu'on peux faire mieux :
 
echo "nombre de spams :" >> /var/spool/filter/report.txt
echo ls /var/spool/spam/out.* | grep -c reported >> /var/spool/filter/report.txt
 
(je ne sais notamment pas comment les ajouter au début du fichier) qui a dit newbie?

Reply

Marsh Posté le 19-06-2003 à 11:02:20    

j'ai testé la première méthode, car j'avais d'autres lignes à ajouter et je ne voyais pas très bien comment faire.
 
je suis donc arriver à ça :
 

Code :
  1. find -name "out.*" ! -name "*.reported" -exec echo "{} :" >> /var/spool/filter/report.txt && cat "{}" | grep Subject | head -1 >> /var/spool/filter/report.txt && cat "{}" | grep 'Content analysis details' >> /var/spool/filter/report.txt && mv "{}" "{}".reported \;


 
et j'obtiens :
 
paramètre manquant pour exec...
 
j'ai fait un man exec (en fait execve) et les parmaètres à mettre sont :
 
 int execve (const char *filename, char *const argv [], char *const envp[]);
 
 
comprends pô tout môa...
 
PS : j'ai essayé aussi sans toucher à ta ligne et ça marche pô non plus :(


Message édité par duch le 19-06-2003 à 11:03:16
Reply

Marsh Posté le 19-06-2003 à 11:12:26    

ha ui pardon ! :o
 


 
  find -name "out.*" ! -name "*.reported" -exec bash -c 'echo "{} :" >> /var/spool/filter/report.txt && cat {} | grep Subject | head -1 >> /var/spool/filter/report.txt && cat {} | grep 'Content analysis details' >> /var/spool/filter/report.txt && mv {} {}.reported' \;

Reply

Marsh Posté le 19-06-2003 à 11:34:22    

bah en fait y'a plus d'erreur mais il ne crée pas le fichier report.txt :(
 
il ne manquerait pas le chemin pouyr accéder au fichiers out.* par hasard?
 
j'ai essayé ça sans résultat :
 

Code :
  1. find -name "/var/spool/spam/out.*" ! -name "/var/spool/spam/*.reported" -exec bash -c 'echo "{} :" >> /var/spool/filter/report.txt && cat {} | grep Subject | head -1 >> /var/spool/filter/report.txt && cat {} | grep 'Content analysis details' >> /var/spool/filter/report.txt && mv {} {}.reported' \;


Reply

Marsh Posté le 19-06-2003 à 11:45:14    

bon en fait après lecture de man find, ça serait plutôt ça :
 

Code :
  1. find -path "/var/spool/spam" -name "out.*" ! -name "*.reported" -exec bash -c 'echo "{} :" >> /var/spool/filter/report.txt && cat {} | grep Subject | head -1 >> /var/spool/filter/report.txt && cat {} | grep 'Content analysis details' >> /var/spool/filter/report.txt && mv {} {}.reported' \;


 
mais ça marche toujours pô, faut-il spécifier deux fois -path?
 
l'erreur est la suivante :
 
./spamreport: /var/spool/filter/report.txt: Aucun fichier ou répertoire de ce type
 
et elle survient à cette ligne :
 

Code :
  1. mail -s "filtre anti-spam" xxx@xxx.com < /var/spool/filter/report.txt


 
ce qui veux dire que le fichier report.txt n'a pas été crée.


Message édité par duch le 17-05-2004 à 09:54:33
Reply

Marsh Posté le 19-06-2003 à 12:43:54    

ben je sais pas, t'as les droits d'écriture dans /var/spool/filter ?

Reply

Marsh Posté le 19-06-2003 à 12:45:54    

bah ouais je teste en root.
 
et puis avec l'autre version du script (avec le for) ça marche nickel, j'comprends pô.
 
même qd je fais

Code :
  1. find -path "/var/spool/spam" -name "out.*"

ça renvois rien...
 
c'est bien comme ça qu'on passe le path?

Reply

Marsh Posté le 19-06-2003 à 12:47:27    

fais voir un 'ls /var/spool/spam' ? :D

Reply

Marsh Posté le 19-06-2003 à 12:57:34    

:D
 

Code :
  1. icilalune:/etc/apache# ls /var/spool/spam
  2. out.20638


Message édité par duch le 19-06-2003 à 12:57:47
Reply

Marsh Posté le 19-06-2003 à 22:40:25    

bon come la directive -path ne marche pô j'ai "rusé" :
 

Code :
  1. cd /var/spool/spam/
  2. find -name "out.*" ! -name "*.reported" -exec bash -c 'echo "{} :" >> ../filter/report.txt && cat {} | grep Subject | head -1 >> ../filter/report.txt && cat {} | grep 'Content analysis details' >> ../filter/report.txt && mv {} {}.reported' \;


 
comme ça, ça marche :D
 
par contre qd je lance le script, il m'affiche tout le contenu des mails dans la console... y'a pas un mode -quiet? (en même temps j'men fous car le script est lancé avec cron mais c'est pas clean)
 
 
autre question (et pis après c'est fini), j'trouve pas comment on écrit au début d'un fichier? ça doit être un truc avec l'opérateur > mais une recherche dans google c'est pô facile...

Reply

Marsh Posté le 20-06-2003 à 09:52:28    

en fait non ça ne marche pô, enfin partiellement
 
voici mon script simplifié :
 

Code :
  1. cd /var/spool/spam/
  2. find -name "out.*" ! -name "*.reported" -exec bash -c 'echo "{} :" >> report.txt && cat {} | grep Subject | head -1 >> report.txt && cat {} | grep 'Content analysis details' >> report.txt && mv {} {}.reported' \;
  3. echo "nombre de spams :" >> report.txt
  4. echo ls out.* | grep -c reported >> report.txt
  5. mail -s "filtre anti-spam" xxx@xxx.com < report.txt
  6. rm report.txt


 
les problèmes sont les suivants :
 
il ne fait pas le mv
donc à chaque que je lance le script, il retraite tous les fichiers
donc echo ls out.* | grep -c reported >> report.txt renvoie 0 (ça c'est pas très grave)
et en plus quand je lance le script il me sort le contenu des mails dans la console :(
 
 
rectification :
 
il ne fait ni le mv ni la seconde commande cat, en fait c'est comme si il ne faisait que ça :
 

Code :
  1. find -name "out.*" ! -name "*.reported" -exec bash -c 'echo "{} :" >> report.txt && cat {} | grep Subject | head -1 >> report.txt


Message édité par duch le 17-05-2004 à 09:54:49
Reply

Marsh Posté le 04-09-2015 à 21:34:28    

Bonjour
 

Code :
  1. $ printf "aaa\naaa\naaa\n"| grep --max-count=1 "aaa"


 
Cette commande ne renverra que la première occurence de "aaa"
 
Le commutateur

--max-count=X

correspond à

-m X

Reply

Marsh Posté le 04-09-2015 à 21:43:28    

up de 12 ans, surement un record


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed