Recherche d'expressions dans un fichier log
zyx
-
zyx -
zyx -
Bonjour,
Je dois écrire un script en shell qui doit rechercher des expressions dans un fichier de log. En fait je dois rechercher une première expression et si elle est trouvée, je dois vérifier si la ligne qui suit correspond à une série d'autres expressions avant d'appliquer des actions.
Mon problème est que je n'arrive pas à lui spécifier que si tu trouves la première expression cherche moi à la ligne d'après telle expression.
Je vous remercie d'avance en espérant que vous pourrez m'aider à résoudre mon problème qui est très urgent.
Je dois écrire un script en shell qui doit rechercher des expressions dans un fichier de log. En fait je dois rechercher une première expression et si elle est trouvée, je dois vérifier si la ligne qui suit correspond à une série d'autres expressions avant d'appliquer des actions.
Mon problème est que je n'arrive pas à lui spécifier que si tu trouves la première expression cherche moi à la ligne d'après telle expression.
Je vous remercie d'avance en espérant que vous pourrez m'aider à résoudre mon problème qui est très urgent.
18 réponses
-
Salut,
Une façon de faire. Si l'expression "EXPR1" est trouvée vérifier si la ligne suivante contient "EXPR2" et le cas échéant la remplacer par "OK", sinon ne rien faire...[tmpfs]$ cat fich blablabla blablabla blabla EXPR1 blabla blabla EXPR2 blabla blablabla blablabla blabla EXPR1 blabla blabla EXPR3 blabla blablabla blablabla blabla EXPR1 blabla blabla EXPR2 blabla blablabla blablabla blabla EXPR1 blabla blabla EXPR3 blabla [tmpfs]$ sed '/EXPR1/{n;/EXPR2/{s/EXPR/OK/}}' fich blablabla blablabla blabla EXPR1 blabla blabla OK2 blabla blablabla blablabla blabla EXPR1 blabla blabla EXPR3 blabla blablabla blablabla blabla EXPR1 blabla blabla OK2 blabla blablabla blablabla blabla EXPR1 blabla blabla EXPR3 blabla [tmpfs]$;-))
-
Merci jipicy de m'avoir répondu
Mais j'ai quelques questions par rapport à ta commande :
sed '/EXPR1/{n;/EXPR2/{s/EXPR/OK/}}' fich
le terme "EXPR" il sert à quoi ici ?
et à quoi correspondent le "n" et le "s""?
Dans mon cas, je veux concaténer la ligne contenant "EXPR1" et celle contenant "EXPR2" quand elle sont sur 2 lignes successives.
-
-
le terme "EXPR" il sert à quoi ici ?
C'était juste un exemple de motif à rechercher dans le fichier "fich"
et à quoi correspondent le "n" et le "s""?
Le "n" passe à la ligne suivante, en fait il vide la mémoire tampon contenant le terme recherché (dans cet exemple) et y stocke la ligne suivante, qui si elle contient le 2nd motif (EXPR2), le substituera grace à la commande "s" par "OK".
Dans mon cas, je veux concaténer la ligne contenant "EXPR1" et celle contenant "EXPR2" quand elle sont sur 2 lignes successives.
Alors il suffit d'adapter :[tmpfs]$ cat fich blablabla blablabla blabla EXPR1 blabla blabla EXPR2 blabla blablabla blablabla blabla EXPR1 blabla blabla EXPR3 blabla blablabla blablabla blabla EXPR1 blabla blabla EXPR2 blabla blablabla blablabla blabla EXPR1 blabla blabla EXPR3 blabla [tmpfs]$ sed '/EXPR1/{N;/EXPR2/{s/\n/ /}}' fich blablabla blablabla blabla EXPR1 blabla blabla EXPR2 blabla blablabla blablabla blabla EXPR1 blabla blabla EXPR3 blabla blablabla blablabla blabla EXPR1 blabla blabla EXPR2 blabla blablabla blablabla blabla EXPR1 blabla blabla EXPR3 blabla [tmpfs]$La commande "N" à l'instar de la commande "n", ne vide pas la mémoire tampon mais ajoute le contenu de la ligne suivante, une fois que c'est fait, il suffit de remplacer le saut de ligne (\n) par un espace (ou ce que tu veux)...
-
-
Bonjour jipicy,
J'ai testé ta commande mais elle ne me concaténe pas les 2 lignes, en fait elle me retourne le contenu du fichier comme si j'avais fait un "cat" seulement. -
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question -
Salut,
Pour que les changements soient permanents il faut en fonction de ta version de "sed" utiliser une redirection dans un nouveau fichier pour les versions antérieures à 4.0.5 ou l'option "-i" (ou "-i.bak" pour faire en même temps une sauvegarde du fichier original)...
-
jipicy,
Je ne m'inquiète pas du fait qu'il me l'affiche sur la sortie standard, ce que je veux soulever c'est que la commande ne me concaténe pas les 2 lignes comme je le veux. Elle se contente juste de me retourner le contenu du fichier. -
Sans voir de quoi il en retourne il m'est assez difficile de t'aider ;-\
Peux-tu afficher un bout de ton fichier, ainsi que ta commande "sed" et surtout avec un exemple "avant/après" nous dire ce que tu veux réellement ?
-
je viens d'essayer avec ton exemple et ça marche.
Et pour mon fichier je crois savoir pourquoi ça marche, je mets mes expressions (qui sont trop longues) dans des variables, je pense que c'est pour ça que ça marche pas.-
Jette un œil à SED - Le remplacement de variables
-
-
Merci jipicy,
j'ai résolu ce problème.
Mais j'ai une autre question. Vu que je travaille sur un fichier de log, je veux qu'il me prenne que les dernières lignes du fichier à chaque fois, comment je peux le faire ? j'ai pensé à la commande tail mais d'après mes premiers essais ça ne passe pas. -
Comment t-y prends-tu ?
tail -50 fich.log | sed '...'
-
ça marche avec "tail -f" sauf que maintenant ça me le redirige plus vers mon fichier résulat comme avant.
Et quand je vire ce fichier de la commande, il me sort bien le bon résultat sur la sortie standard. -
pardon j'avais pas vu ta réponse là:
Avec 'tail -f" ça ne sera possible qu'en passant par un "fifo" à mon avis...
C'est à dire ? -
Mon problème est maintenant comment récupérer que les dernières lignes de log à chaque fois et après chaque traitement rediriger le tout vers un autre fichier.
De l'aide SVP. -
tail -n (ou n est le nombre de lignes à récupérer) au lieu de tail -f...
-
Le problème est que je ne connais pas le nombre de lignes que je peux avoir à chaque fois.
Et si je mets un nombre trop petit, je vais louper des lignes de log et si le nombre est très grand je vais reprendre des lignes que j'ai déjà traitées. -
Bon je ne t'ai pas oublié, mais l'affaire est plus complexe qu'il n'y parait :-\
Donc pour en revenir à ton problème et aux tubes nommés (fifo), voilà un exemple à mettre en pratique en reprenant mon exemple du post #3.
L'idée générale, c'est de créer un fifo (tube) dans lequel sera envoyé la sortie de la commande tail -f fichier.log. La commande sed quant à elle, ira lire et récupérer ce qui nous intéresse dans le tube et l'enverra dans un autre fichier (mon.log).
Je dois générer un semblant de fichier de log, pour ça j'ai fait un petit script qui va me créer mon fichier (fich.log).
Le script :#! /bin/bash i=1 EXPR="EXPR" while [ "$i" -lt "50000" ] do if [ "${i: -1}" == "3" ] || [ "${i: -1}" == "7" ] then EXPR="EXPR2" else EXPR="EXPR" fi echo -e "blablabla blablabla blabla EXPR1 blabla blabla $EXPR blabla $i" >> fich.log ((i++)) sleep 1 doneLe résultat sera du genre :blablabla blabla EXPR1 blabla blabla EXPR blabla 2 blablabla blablabla blabla EXPR1 blabla blabla EXPR2 blabla 3 blablabla blablabla blabla EXPR1 blabla blabla EXPR blabla 4 blablabla blablabla blabla EXPR1 blabla blabla EXPR blabla 5 blablabla blablabla blabla EXPR1 blabla blabla EXPR blabla 6 blablabla blablabla blabla EXPR1 blabla blabla EXPR2 blabla 7 blablabla blablabla
Avec comme tu peux le voir le motif qui nous intéresse sur chaque ligne finissant par un 3 ou un 7.
Puis créer le fifo :mkfifo tube
Ensuite on lance la commande sed qui va donc lire et récupérer les données dans le tube :sed -n ' /EXPR1/{ N /EXPR2/{ s/\n/ / w mon.log } }' < tube &On lance le script qui doit générer le fichier de log :./foo.sh
Puis la commande tail -f:tail -f fich.log > tube
A partir de là, le fichier "mon.log" se remplit au fur et à mesure que les données sont envoyées dans le tube...$ cat mon.log blabla EXPR1 blabla blabla EXPR2 blabla 33 blabla EXPR1 blabla blabla EXPR2 blabla 37 blabla EXPR1 blabla blabla EXPR2 blabla 43 blabla EXPR1 blabla blabla EXPR2 blabla 47 blabla EXPR1 blabla blabla EXPR2 blabla 53 blabla EXPR1 blabla blabla EXPR2 blabla 57 blabla EXPR1 blabla blabla EXPR2 blabla 63 ... ... blabla EXPR1 blabla blabla EXPR2 blabla 123 blabla EXPR1 blabla blabla EXPR2 blabla 127 ...
Si tu veux voir la sortie de tail -f à l'écran, rajoute un "pipe" et un "tee" :tail -f fich.log | tee tube
Bien évidemment, il ne faut pas que les données arrivent ligne par ligne sans quoi il risque d'y avoir un hic ;-(
;-)) -
Merci jipicy,
je viens de voir ta réponse, je vais tester ton code voir si ça marche.
Je vais revenir sur la commande "sed", est ce qu'il y a possibilité de faire la même chose que dans la réponse 3 mais cette fois ci en lui spécifiant si tu me trouves une ligne contenant A et que la ligne d'après contient B ou si tu me trouves une ligne contenant C et la ligne d'après contenant D concatène les moi.
Merci -
Alors oui le "OU" peut se traduire avec "sed" avec la syntaxe "\|" (un pipe protégé par un anti-slash) :
MOTIF1\|MOTIF2
Pour reprendre avec l'exemple du post #3 (je l'ai un peu modifié pour mieux illustrer) :[tmpfs]$ cat fich.txt blablabla blablabla blabla EXPRA blabla blabla EXPR2 blabla blablabla blablabla blabla EXPRA blabla blabla EXPR3 blabla blablabla blablabla blabla EXPRC blabla blabla EXPR2 blabla blablabla blablabla blabla EXPRA blabla blabla EXPR3 blabla blablabla blablabla blabla EXPRC blabla blabla EXPR3 blabla [tmpfs]$ sed '/EXPRA\|C/{N;/EXPR2/{s/\n/ /}}' fich.txt blablabla blablabla blabla EXPRA blabla blabla EXPR2 blabla blablabla blablabla blabla EXPRA blabla blabla EXPR3 blabla blablabla blablabla blabla EXPRC blabla blabla EXPR2 blabla blablabla blablabla blabla EXPRA blabla blabla EXPR3 blabla blablabla blablabla blabla EXPRC blabla blabla EXPR3 blabla [tmpfs]$Donc, si la ligne contient EXPRA ou EXPRC on ajoute la ligne suivante, et si elle contient EXPR2 on concatène les 2 lignes.
Par contre pour ta demande, il faut écrire une syntaxe pour chaque motif dans la mesure où sed lit en entrée une ligne et lui applique le script (chaque commande qui compose le script en fait) et n'applique ladite commande que si elle satisfait à (aux) condition(s) explicitement. Donc en mettant chaque condition à la suite :sed ' /MOTIFA/{ N /MOTIFB/{ s/\n/ / } } /MOTIFC/{ N /MOTIFD/{ s/\n/ / } } ' fichierchaque ligne en entrée sera comparée successivement...