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.
A voir également:
- Recherche d'expressions dans un fichier log
- Fichier bin - Guide
- Comment ouvrir un fichier epub ? - Guide
- Comment réduire la taille d'un fichier - Guide
- Fichier rar - Guide
- Fichier .dat - Guide
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...
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]$ ;-))
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 :
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.
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)...
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.
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 ?
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.
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.
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.
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.
ç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.
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 ?
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.
De l'aide SVP.
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.
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 :
Puis créer le fifo :
;-))
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 blablablaAvec 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 tubeEnsuite 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.shPuis la commande tail -f:
tail -f fich.log > tubeA 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 tubeBien é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
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) :
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 :
MOTIF1\|MOTIF2Pour 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...
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.