Recherche d'expressions dans un fichier log

Fermé
zyx - 5 août 2008 à 17:51
 zyx - 12 août 2008 à 23:43
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.
A voir également:

18 réponses

jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
5 août 2008 à 18:13
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]$  
;-))
0
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.
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
5 août 2008 à 20:39
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)...

0
Merci jipicy c'est très gentil à toi.

Je testerai ça.
0
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.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
6 août 2008 à 10:21
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)...
0
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.
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
6 août 2008 à 10:33
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 ?
0
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.
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
6 août 2008 à 11:08
0
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.
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
6 août 2008 à 14:47
Comment t-y prends-tu ?

tail -50 fich.log | sed '...'
0
oui pareil mais avec "tail -f"

J'avoue que les scripts c'est pas mon fort.
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897 > zyx
6 août 2008 à 16:52
Avec 'tail -f" ça ne sera possible qu'en passant par un "fifo" à mon avis...
0
ç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.
0
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 ?
0
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.
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
7 août 2008 à 10:26
tail -n (ou n est le nombre de lignes à récupérer) au lieu de tail -f...
0
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.
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
7 août 2008 à 20:39
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
done
Le 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 ;-(

;-))
0
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
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
11 août 2008 à 10:32
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/ /
}
}
' fichier
chaque ligne en entrée sera comparée successivement...
0
Bonjour,

Merci jipicy de tes réponses,
j'ai pas eu le temps de m'en occuper mais demain je le testerai.
0