OVH Cloud OVH Cloud

[sed] permutation de triplets de lignes - besoin d'un avis d'expert

8 réponses
Avatar
Patrick 'Zener' Brunet
Bonsoir.

J'ai fait un script SED pour extraire des données d'une page Web, et là il
me reste à mettre la touche finale: permuter des triplets de lignes.

Ca marche, mais pas bien, et je n'arrive pas à trouver la subtilité.
Comme je préfère comprendre que jouer à l'alchimiste, je voudrais un avis
d'expert...

Donc à ce stade on arrive à un fichier de données de la forme:

ARTICLE=Machin truc
######
PRIX=0,07
ETAT=occasion
VENDEUR=Sean Connery
######
PRIX=7,65
ETAT=neuf
VENDEUR=Clint Eastwood
######
PRIX=3,57
ETAT=bon état
VENDEUR=Yves Montand
######
...

et le but est de traiter chaque triplet pour faire passer la ligne VENDEUR
en première position.

Donc j'envoie cette commande:

sed -e '/^PRIX/N;N;s/\([^\n]*\)\n\([^\n]*\)\n\([^\n]*\)/\3\n\1\n\2/' <infile
>outfile

Dans ma tête ça devrait faire ce qui suit:
- pour toute ligne commençant par "PRIX",
- - concaténer les deux suivantes
- - selectionner les contenus des trois lignes
- - les reproduire en trois lignes dans l'ordre 3-1-2.

Ben en fait ça marche mais ça ne traite que le premier triplet.

Alors je me dis que c'est parce que le séparateur en dièses fait barrage...
Alors je rajoute à la fin: ;N
... et là ça les traite tous sauf le premier :'-(

Bref, j'ai raté un truc dans la logique du flux de données avalées et
recrachées par SED.

Normalement, l'adresse /^PRIX/ devrait déclencher la commande pour *tous*
les triplets, non ?

Merci de vos explications.
Cordialement,

--
/***************************************\
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
\***************************************/

8 réponses

Avatar
Stephane Chazelas
2006-10-10, 22:57(+02), Patrick 'Zener' Brunet:
[...]
sed -e '/^PRIX/N;N;s/([^n]*)n([^n]*)n([^n]*)/3n1n2/' <infile
outfile


Dans ma tête ça devrait faire ce qui suit:
- pour toute ligne commençant par "PRIX",
- - concaténer les deux suivantes
- - selectionner les contenus des trois lignes
- - les reproduire en trois lignes dans l'ordre 3-1-2.
[...]

Normalement, l'adresse /^PRIX/ devrait déclencher la commande pour *tous*
les triplets, non ?
[...]


Non, /^PRIX/N fait un N pour les lignes matchant /^PRIX/, les
autres commandes sont executees pour toutes les lignes puisque
tu n'y mets pas de condition. et [^n] veut dire tout sauf et
n.

sed '/^PRIX{N;N;s/(.*n)(.*)(n)(.*)/4312/;}'

ou

sed -ne '/^PRIX/{h;n;H;n;G;}' -e p


--
Stéphane


Avatar
Stephane Chazelas
2006-10-10, 22:42(+01), Stephane Chazelas:
[...]
sed '/^PRIX{N;N;s/(.*n)(.*)(n)(.*)/4312/;}'


ou

sed '/^PRIX{N;N;s/(.*n.*)(n)(.*)/321/;}'


ou

sed -ne '/^PRIX/{h;n;H;n;G;}' -e p


ou

sed -ne '/^PRIX/{N;h;n;G;}' -e p

--
Stéphane

Avatar
Patrick 'Zener' Brunet
Bonjour.

Je réponds à Stephane Chazelas
2006-10-10, 22:57(+02), Patrick 'Zener' Brunet:
[...]
sed -e '/^PRIX/N;N;s/([^n]*)n([^n]*)n([^n]*)/3n1n2/'
<infile > outfile

Dans ma tête ça devrait faire ce qui suit:
- pour toute ligne commençant par "PRIX",
- - concaténer les deux suivantes
- - selectionner les contenus des trois lignes
- - les reproduire en trois lignes dans l'ordre 3-1-2.
[...]

Normalement, l'adresse /^PRIX/ devrait déclencher la commande pour
*tous* les triplets, non ?
[...]


Non, /^PRIX/N fait un N pour les lignes matchant /^PRIX/, les
autres commandes sont executees pour toutes les lignes puisque
tu n'y mets pas de condition. et [^n] veut dire tout sauf et n.



Ah sacrebleu !
Et pourtant j'ai toujours vu des exemples avec t par exemple pour un Tab.

J'imagine que c'est conçu pour travailler sur une seule ligne (N; étant une
extension), et donc le n est ignoré dans une classe ?


sed '/^PRIX{N;N;s/(.*n)(.*)(n)(.*)/4312/;}'


Pourquoi ne pas fermer l'adresse ?

sed '/^PRIX/{N;N;s/(.*n)(.*)(n)(.*)/4312/;}'

En fait j'ai réécrit ma commande ainsi:

sed '/^PRIX/{N;N;s/(.*)n(.*)n(.*)/3n1n2/}'

...et ça fait ce que je voulais.


ou

sed -ne '/^PRIX/{h;n;H;n;G;}' -e p


Oui... :-? Hmmmmm...
J'avoue que je ne maîtrise pas à ce point toutes ces commandes. J'ai cherché
un site expliquant très clairement le cycle de SED et comment chacune le
modifie, c'est pas encore clair.

Par exemple j'en ai une autre plus haut dans le traitement qui a cette
allure:

sed -e ':a' -e '/ETAT=$/N;s/ETAT=n/ETAT=/' -e 'ta'

et qui sert à ramener sur une seule ligne la forme:

ETAT <ligne vide optionnelle>
occasion

Et bien celle-là je n'arrive pas à la faire migrer dans le script SED, je
dois la laisser sous cette forme. C'est moche :-(
Le goto est réputé "for tricky users" semble-t-il...
Evidemment je peux adapter l'exemple précédent, mais les boîtes noires qui
le restent, c'est pas mon truc.

En tout cas merci beaucoup pour l'information.

Cordialement,

--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/


Avatar
Stephane Chazelas
2006-10-11, 20:07(+02), Patrick 'Zener' Brunet:
[...]
Et pourtant j'ai toujours vu des exemples avec t par exemple pour un Tab.

J'imagine que c'est conçu pour travailler sur une seule ligne (N; étant une
extension), et donc le n est ignoré dans une classe ?
[...]


Non, c'est juste que c'est pas tres bien concu. Cela dit, ca
marchera pas mieux avec t a moins d'avoir un sed pas standard.

sed '/^PRIX{N;N;s/(.*n)(.*)(n)(.*)/4312/;}'


Pourquoi ne pas fermer l'adresse ?

sed '/^PRIX/{N;N;s/(.*n)(.*)(n)(.*)/4312/;}'


Ah oui, sorry.

[...]
sed -ne '/^PRIX/{h;n;H;n;G;}' -e p


Oui... :-? Hmmmmm...
J'avoue que je ne maîtrise pas à ce point toutes ces commandes. J'ai cherché
un site expliquant très clairement le cycle de SED et comment chacune le
modifie, c'est pas encore clair.


Ben c'est tres simple en fait. Regarde la page de man de sed
sous Solaris, je crois qu'elle explique bien si je me rappelle
bien.


Par exemple j'en ai une autre plus haut dans le traitement qui a cette
allure:

sed -e ':a' -e '/ETAT=$/N;s/ETAT=n/ETAT=/' -e 'ta'

et qui sert à ramener sur une seule ligne la forme:

ETAT > <ligne vide optionnelle>
occasion

Et bien celle-là je n'arrive pas à la faire migrer dans le script SED, je
dois la laisser sous cette forme. C'est moche :-(


Qu'est-ce que t'as essayé et qui ne marche pas?

--
Stéphane


Avatar
Patrick 'Zener' Brunet
Bonjour.

Je réponds à Stephane Chazelas
2006-10-11, 20:07(+02), Patrick 'Zener' Brunet:
[...]
Par exemple j'en ai une autre plus haut dans le traitement qui a
cette allure:

sed -e ':a' -e '/ETAT=$/N;s/ETAT=n/ETAT=/' -e 'ta'

et qui sert à ramener sur une seule ligne la forme:

ETAT >> <ligne vide optionnelle>
occasion

Et bien celle-là je n'arrive pas à la faire migrer dans le script
SED, je dois la laisser sous cette forme. C'est moche :-(


Qu'est-ce que t'as essayé et qui ne marche pas?


Et bien j'ai commencé par virer la ligne vide optionnelle avec:

/^$/d

...et ensuite le seul moyen de regrouper une telle commande sur une ligne de
script SED me paraît être:

{:a;/ETAT=$/N;s/ETAT=n/ETAT=/;ta}

Mais le goto + re-match ne fonctionne pas, je récupère:

ETAT occasion

J'ai essayé d'autres trucs, mais sans plus de succès, voire une faute de
syntaxe.

Je vais encore essayer... Merci pour cette aide précieuse.

Cordialement,

--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/


Avatar
Stan
"Patrick 'Zener' Brunet" a écrit dans
le message de news: egh1fg$ebu$
Bonsoir.

J'ai fait un script SED pour extraire des données d'une page Web, et là il
me reste à mettre la touche finale: permuter des triplets de lignes.



Sinon, en AWK, ça ce fait facilement ;-)

/PRIX/ { prix=$0; cond++; }
/ETAT/ { prix=$0; cond++; }
/VENDEUR/ { prix=$0; cond++; }

cond==3{
print vendeur;
print etat;
print prix;
cond = 0;
}

Je pense aussi que les traitements
préalables que vous faites en SED peuvent
être remplacé en AWK ( perso, je trouve que c'est plus lisible ).

--
-Stan

Avatar
Pascal Bourguignon
"Stan" writes:

"Patrick 'Zener' Brunet" a écrit dans
le message de news: egh1fg$ebu$
Bonsoir.

J'ai fait un script SED pour extraire des données d'une page Web, et là il
me reste à mettre la touche finale: permuter des triplets de lignes.



Sinon, en AWK, ça ce fait facilement ;-)

/PRIX/ { prix=$0; cond++; }
/ETAT/ { prix=$0; cond++; }
/VENDEUR/ { prix=$0; cond++; }

cond==3{
print vendeur;
print etat;
print prix;
cond = 0;
}

Je pense aussi que les traitements
préalables que vous faites en SED peuvent
être remplacé en AWK ( perso, je trouve que c'est plus lisible ).


/PRIX/ { prix=$0; }
/ETAT/ { etat=$0; }
/VENDEUR/ { vendeur=$0;
print vendeur;
print etat;
print prix;
}

--
__Pascal Bourguignon__ http://www.informatimago.com/

In a World without Walls and Fences,
who needs Windows and Gates?


Avatar
Patrick 'Zener' Brunet
Bonjour.

Je réponds à Pascal Bourguignon
"Stan" writes:
"Patrick 'Zener' Brunet" a
écrit dans le message de news: egh1fg$ebu$
Bonsoir.

J'ai fait un script SED pour extraire des données d'une page Web,
et là il me reste à mettre la touche finale: permuter des triplets
de lignes.


Sinon, en AWK, ça ce fait facilement ;-)

/PRIX/ { prix=$0; cond++; }
/ETAT/ { prix=$0; cond++; }
/VENDEUR/ { prix=$0; cond++; }

cond==3{
print vendeur;
print etat;
print prix;
cond = 0;
}

Je pense aussi que les traitements
préalables que vous faites en SED peuvent
être remplacé en AWK ( perso, je trouve que c'est plus lisible ).


/PRIX/ { prix=$0; }
/ETAT/ { etat=$0; }
/VENDEUR/ { vendeur=$0;
print vendeur;
print etat;
print prix;
}


Oui, c'est possible... J'avoue que je n'en fais pas une folie, c'est
purement utilitaire.
Mon plaisir créatif se place ailleurs...

Mais à l'occasion, j'étudierai aussi Awk.

Merci, Cordialement,

--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/