Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Parser une ligne avec des clés=valeurs contenant des espaces (csh)

Aucune réponse
Avatar
Kevin Denis
Bonjour,

je dois parser des lignes de log construites sur un schéma clé=valeur
ressemblant à:

id=AAA type=BBB value=CCC msg=\"aaa bbb ccc ddd eee\" value2=xxx
value3=\"eee eee eee\"
id=AA2 type=BB2 value=CC2 value2=xx2 value3=\"eee eee eee\"
etc...

Les lignes n\'ont pas forcément toutes les clés renseignées.

Je souhaite parser ces lignes pour n\'en conserver qu\'une partie, par
exemple msg, id, value2 et value3. Je ne trouve pas de moyen simple
pour parser ces lignes. Mon plus gros problème vient des espaces dans
certaines valeurs et de l\'absence de clés dans d\'autres.
J\'en ai besoin pour faire:

tail -f /var/log/my_log | parse_line.sh

C\'est sous FreeBSD, avec csh (pas de bash disponible) et les utilitaires
classiques (sed, cut, awk, etc..)

Merci
--
Kevin

10 réponses

1 2
Avatar
Nicolas George
Kevin Denis , dans le message
, a écrit :
Mon plus gros problème vient des espaces dans
certaines valeurs et de l'absence de clés dans d'autres.



Donc il te faut la description précise et détaillée de la syntaxe.

C'est sous FreeBSD, avec csh (pas de bash disponible) et les utilitaires
classiques (sed, cut, awk, etc..)



Donc entre autres c99.
Avatar
Lucas Levrel
Le 25 mars 2015, Kevin Denis a écrit :

idªA type»B valueÌC msg="aaa bbb ccc ddd eee" value2=xxx
value3="eee eee eee"
idª2 type»2 valueÌ2 value2=xx2 value3="eee eee eee"
etc...

Les lignes n'ont pas forcément toutes les clés renseignées.

Je souhaite parser ces lignes pour n'en conserver qu'une partie, par
exemple msg, id, value2 et value3. Je ne trouve pas de moyen simple
pour parser ces lignes. Mon plus gros problème vient des espaces dans
certaines valeurs et de l'absence de clés dans d'autres.

echo valueÌC msg="aaa bbb ccc ddd eee" value2=xxx


| egrep -o 'msg="[A-Za-z ]*"|msg=[A-Za-z]*'
msg="aaa bbb ccc ddd eee"

echo valueÌC msgªa value2=xxx


| egrep -o 'msg="[A-Za-z ]*"|msg=[A-Za-z]*'
msgªa

Est-ce que ça aide ?

--
LL
Ἕν οἶδα ὅτι οὐδὲν οἶδα (Σωκράτης)
Avatar
Kevin Denis
Le 25-03-2015, Lucas Levrel a écrit :
Je souhaite parser ces lignes pour n'en conserver qu'une partie, par
exemple msg, id, value2 et value3. Je ne trouve pas de moyen simple
pour parser ces lignes. Mon plus gros problème vient des espaces dans
certaines valeurs et de l'absence de clés dans d'autres.



echo valueÌC msg="aaa bbb ccc ddd eee" value2=xxx


| egrep -o 'msg="[A-Za-z ]*"|msg=[A-Za-z]*'
msg="aaa bbb ccc ddd eee"

echo valueÌC msgªa value2=xxx


| egrep -o 'msg="[A-Za-z ]*"|msg=[A-Za-z]*'
msgªa

Est-ce que ça aide ?



$ egrep
egrep: Command not found.

J'ai quand même grep -E qui me permet de faire ce genre de choses:
grep -E -o 'msg="[A-Za-z0-9 -.:]*"|value2=[a-z]*'

Ca marche bien, mais l'ensemble des clés choisies sont affichées sur
plusieurs lignes:

tail log | grep -E -o 'msg="[A-Za-z0-9 -.:]*"|value2=[a-z]*'
msg="XXX YYY"
value2=ssh
msg="aaa bbb"
value2«c

Et je retombe dans un problème : je peux concaténer les lignes
en une seule avec un | sed 'N;s/n/ /' ou équivalent avec awk, mais comme
certaines lignes de log n'ont pas toutes les clés, cela finit par tout
décaler :-/

Ca va finir avec un oneliner abominable du genre:
tail -f log | grep (...) | tr 'n' ' ' | sed s/msg/µmsg/g | tr 'µ' 'n'

ou mieux, un:
ssh server tail -f log | script_local_evolué

Merci pour l'idée en tout cas :)
--
Kevin
Avatar
Lucas Levrel
Le 25 mars 2015, Kevin Denis a écrit :

$ egrep
egrep: Command not found.



:-)

J'ai quand même grep -E qui me permet de faire ce genre de choses:
grep -E -o 'msg="[A-Za-z0-9 -.:]*"|value2=[a-z]*'

Ca marche bien, mais l'ensemble des clés choisies sont affichées sur
plusieurs lignes:

tail log | grep -E -o 'msg="[A-Za-z0-9 -.:]*"|value2=[a-z]*'
msg="XXX YYY"
value2=ssh
msg="aaa bbb"
value2«c



Est-ce qu'un truc comme ça est possible en csh :
--- parse_line.sh ---
while read LINE
do
MSG=$(echo $LINE | grep -E -o ...)
VALUE2=$(echo $LINE | ...)
...
done
echo $MSG $VALUE2 ...
---------------------
?

(Tu as bien dit que tu pouvais envoyer le log dans un script, tu n'es pas
contraint à un one-liner ?)

--
LL
Ἕν οἶδα ὅτι οὐδὲν οἶδα (Σωκράτης)
Avatar
Nicolas George
Lucas Levrel , dans le message
, a écrit :
while read LINE



Ça commence mal si la ligne contient des backslashes.

do
MSG=$(echo $LINE | grep -E -o ...)



Et ça continue de même.

Des scripts qui ne marchent pas, on peut en faire en csh aussi, oui, pas de
problème.
Avatar
Kevin Denis
Le 25-03-2015, Lucas Levrel a écrit :
J'ai quand même grep -E qui me permet de faire ce genre de choses:
grep -E -o 'msg="[A-Za-z0-9 -.:]*"|value2=[a-z]*'

Ca marche bien, mais l'ensemble des clés choisies sont affichées sur
plusieurs lignes:

tail log | grep -E -o 'msg="[A-Za-z0-9 -.:]*"|value2=[a-z]*'
msg="XXX YYY"
value2=ssh
msg="aaa bbb"
value2«c



Est-ce qu'un truc comme ça est possible en csh :
--- parse_line.sh ---
while read LINE



J'avais tenté, mais le while read ne semble pas exister en csh:
http://www.linuxquestions.org/questions/programming-9/csh-while-read-738708/
question: Is there an equivalent in csh to bash's while read cariable list?
Answer: AFAIK, the answer is no.

(Tu as bien dit que tu pouvais envoyer le log dans un script, tu n'es pas
contraint à un one-liner ?)



Non. C'est une appliance Netasq, donc un FreeBSD dedans. Je pensais qu'il
y avait moyen d'obtenir un one-liner :) mais je vais faire un script.
--
Kevin
Avatar
Benoit Izac
Bonjour,

le 26/03/2015 à 10:06, Kevin Denis a écrit dans le message
:

Est-ce qu'un truc comme ça est possible en csh :
--- parse_line.sh ---
while read LINE



J'avais tenté, mais le while read ne semble pas exister en csh:
http://www.linuxquestions.org/questions/programming-9/csh-while-read-738708/
question: Is there an equivalent in csh to bash's while read cariable list?
Answer: AFAIK, the answer is no.



Donc pourquoi utiliser csh (tcsh) plutôt que sh (ash il me semble) ?

--
Benoit Izac
Avatar
Lucas Levrel
Le 25 mars 2015, Nicolas George a écrit :

while read LINE



Ça commence mal si la ligne contient des backslashes.

do
MSG=$(echo $LINE | grep -E -o ...)



Et ça continue de même.



Sans doute. Comme les points de suspension le suggèrent, ce sont des
pistes.

En l'occurence, seul l'OP sait ce qu'il est susceptible d'y avoir.


Des scripts qui ne marchent pas, on peut en faire en csh aussi, oui, pas de
problème.



Ouaip, c'est comme les réponses inutiles, on peut les faire dans toutes
les langues.


--
LL
Ἕν οἶδα ὅτι οὐδὲν οἶδα (Σωκράτης)
Avatar
Nicolas George
Lucas Levrel , dans le message
, a écrit :
Ouaip, c'est comme les réponses inutiles



Souligner les erreurs classiques dans la rédaction de scripts shell, erreurs
classiques qui conduisent régulièrement à des pertes de données
accidentelles ou des trous de sécurité...

À toi de voir si tu considères ça comme inutile.
Avatar
Paul Gaborit
À (at) 27 Mar 2015 12:52:36 GMT,
Nicolas George <nicolas$ écrivait (wrote):

Lucas Levrel , dans le message
, a écrit :
Ouaip, c'est comme les réponses inutiles



Souligner les erreurs classiques dans la rédaction de scripts shell, erreurs
classiques qui conduisent régulièrement à des pertes de données
accidentelles ou des trous de sécurité...

À toi de voir si tu considères ça comme inutile.



Plutôt que de souligner les erreurs, il serait bon de proposer le moyen
de ne pas les faire !

Et le premier moyen, bien connu de tous ceux qui développent proprement
en shell, est de ne pas utiliser (t)csh comme shell pour les scripts.

Il vaut mieux choisir sh (celui de FreeBSD n'est pas bash) ce qui oblige
à faire du shell standard POSIX. Ou alors choisir bash, ksh ou zsh qui
sont bien plus puissants mais dont la disponibilité n'est pas garantie
partout.

--
Paul Gaborit - <http://perso.mines-albi.fr/~gaborit/>
1 2