#1 Le 23/12/2009, à 15:22
- YvanD
[Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Salut tout le monde,
J'ai un problème, je suis en train de faire un script bash (utilisant principalement sed) qui convertisse des pages html (pas du tout valide, loin de là) en xhtml (pour la rendre valide).
Je vais essayer d'illustrer mon problème sur un exemple simple (qui est fictif).
Je souhaite transformer ce texte
Partie 1 <span style=...>...</span> Partie 2 <span style=...>...</span> Partie 3
en ceci
Partie 1 Partie 2 Partie 3
Bien sur le but de ce script n'est pas d'enlever toutes ces balises mais mon pb, c'est que la commande
echo 'Partie 1 <span style='...'>...</span> Partie 2 <span style='...'>...</span> Partie 3' | sed 's|<span.*<\/span>||g'
me renvoie :
Partie 1 Partie 3 # Oups Partie 2 a disparu !!!
« Donc .* prend le max de longueur possible » (il s'arrête au dernier trouvé)
Mais comment lui dire que non ??
J'espère avoir clair. Merci de votre aide.
Dernière modification par YvanD (Le 29/12/2009, à 18:06)
Hors ligne
#2 Le 23/12/2009, à 15:29
- sputnick
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
echo 'Partie 1 <span style='...'>...</span> Partie 2 <span style='...'>...</span> Partie 3' | \
sed -r 's@</?span[^>]*>@@g'
Dernière modification par sputnick (Le 23/12/2009, à 15:33)
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#3 Le 23/12/2009, à 15:35
- becket
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
sed 's|<[^s]*span[^>]*>||g'
Hors ligne
#4 Le 23/12/2009, à 15:36
- YvanD
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Un grand merci sputnick.
J'essaye de comprendre, mais je bloque sur la signification de [^>].
Hors ligne
#5 Le 23/12/2009, à 15:38
- sputnick
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
tout ce qui n'est pas un >
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#6 Le 23/12/2009, à 17:18
- YvanD
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
J'ai encore une question :
Je veux supprimer les balises inutiles genre <span>blabla</span> mais conserver les balises span utiles (qui ont au moins un attribut).
Je veux remplacer ça
Ceci est un <span>span inutile</span> mais voici un <span class='uneclasseqcq'>span utile</span> !
par ceci
Ceci est un span inutile mais voici un span utile !
EDIT : je pensais au métacaractère & mais je n'y arrive pas.
Dernière modification par YvanD (Le 23/12/2009, à 17:18)
Hors ligne
#7 Le 23/12/2009, à 19:12
- becket
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
sed 's|<span>\([^<]*\)<\/span>|\1|g'
Hors ligne
#8 Le 26/12/2009, à 17:20
- YvanD
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Merci encore becket.
J'ai (encore) une question
Je voudrais supprimer les commentaires html.
Mais je rencontre un problème pour certains commentaires, voici un exemple de commentaire que je voudrais supprimer proprement.
<!--<xml>...-...</xml>-->
En fait le problème c'est que [^>] ne marche pas car il y des > dans <!-- --> donc il faudrait un truc du genre [^-->] mais ceci ne marche pas.
Pourriez-vous me dire la syntaxe correcte à utiliser.
EDIT : bien sur je ne veux/peux pas utiliser s|<!--.*-->||g car il y a plusieurs commentaires sur une même ligne.
Dernière modification par YvanD (Le 26/12/2009, à 17:21)
Hors ligne
#9 Le 26/12/2009, à 22:30
- sputnick
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
sed 's@^[[:space:]]*<!--\(<xml>.*</xml>\)-->$@\1@'
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#10 Le 28/12/2009, à 11:38
- YvanD
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Merci sputnick.
En fait dans un commentaire il peut y avoir n'importe quel balise par forcément au début et à la fin du commentaire...
Je voudrais simplement arriver à dire à sed, tu t'arrêtes dès que tu vois "-->".
J'ai essayé cette syntaxe "<!--[^-->]*-->" ça ne marche pas, ni "<!--[^\(-->\)]*-->".
Hors ligne
#11 Le 28/12/2009, à 14:19
- Totor
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Bonjour,
Ce n'est pas si simple que cela car je suppose que le commentaire peut être multi-lignes. il se peut aussi qu'il y ait plusieurs commentaires sur la même ligne.
Je n'ai pas poussé mes tests mais cela devrait faire l'affaire :
sed '/<!--/ { :deb; $ b fin; s/-->/&/1; t fin; N; b deb; :fin s/-->/@/1;s/\(^<!--\)*<!--[^@]*@\(.*\)/\1\2/1; s/<!--/&/1; t deb }' fichier
la seule restriction : il ne faut pas que le caractère @ soit déjà présent dans le commentaire (ou avant). j'ai du utiliser cette astuce
EDIT :
légèrement mieux :
sed '/<!--/ { :deb; $ b fin; s/-->/&/1; t fin; N; b deb; :fin s/-->/@/1;s/<!--[^@]*@\(.*\)/\1/1; s/<!--/&/1; t deb }' fichier
chaine testée :
echo -e '<!--jklj-->dsgsdg<!--n\nnn--> xwcv <!--jghj-->C'|sed '/<!--/ { :deb; $ b fin; s/-->/&/1; t fin; N; b deb; :fin s/-->/@/1;s/<!--[^@]*@\(.*\)/\1/1; s/<!--/&/1; t deb }'
Dernière modification par Totor (Le 28/12/2009, à 18:43)
-- Lucid Lynx --
Hors ligne
#12 Le 28/12/2009, à 20:08
- YvanD
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Ça m'a l'air très complexe.
En fait le fichier html est sur UNE seule ligne (en fait mon script fait au début « tr '\n' ' ' » (à la fin le contraire). Aurais-tu alors plus simple
Dernière modification par YvanD (Le 28/12/2009, à 20:08)
Hors ligne
#13 Le 28/12/2009, à 22:01
- sputnick
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Quel est le but ultime YvanD ?
Si c'est parser proprement du XML il existe des bindings dans tous les languages de 3e génération. Perl a la magnifique : XML::Simple ... comme son nom l'indique...
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#14 Le 28/12/2009, à 22:18
- sputnick
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Ce que je comprends de ta demande :
sed -r 's@<!--(.*)-->@\1@' <file>
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#15 Le 28/12/2009, à 23:37
- Totor
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Ce que je comprends de ta demande :
sed -r 's@<!--(.*)-->@\1@' <file>
là y'a pas de suppression de commentaire mais des balises commentaires.
Par ailleurs, ce n'est pas suffisant car cela supprime la toute première balise <!-- et la toute dernière balise --> (même s'il y en a d'intermédaires).
exemple :
$echo '<!--A-->B<!--C-->D<!--E-->F'|sed -r 's@<!--(.*)-->@\1@'
A-->B<!--C-->D<!--EF
alors qu'il souhaiterait obtenir l'un des résultats suivant :
1 : B<!--C-->D<!--E-->F
ou
2 : <!--A-->BD<!--E-->F
ou
3 : BDF
En tout cas, c'est ce que je comprend ...
Je voudrais supprimer les commentaires html.
je reprend la question de sputnick : que souhaites-tu exactement ?
-- supprimer le premier commentaire (ex 1) ?
-- supprimer un commentaire parmis d'autres (ex 2) ?
-- supprimer tous les commentaires (ex 3) ?
-- supprimer les balises commentaire ?
si tu n'exprimes pas clairement ton besoin, on ne pourra pas t'aider.
Note : le tr '\n' ' ' n'est pas utile. Par ailleurs l'inverse faussera ton fichier car TOUS les blancs seront transformés en saut de ligne impliquant très probablement un changement de mise en forme, de texte...
Enfin, sed n'est pas trivial... son utilisation est-elle une contrainte ?
-- Lucid Lynx --
Hors ligne
#16 Le 29/12/2009, à 11:16
- YvanD
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Merci de votre aide.
Explications :
Je souhaite convertir « à la main » (avec bash et sed) un fichier html truffé d'erreur (réalisé jadis avec un logiciel sous Windobe©), je souhaite donc les corriger avec mon script (il est déjà bien avancé et fonctionne plutôt pas mal mais il reste quelques améliorations).
D'abord le script fait un « tr '\n' '%' » (et « tr '\r' '%' » [le fichier contient des \n et des \r] et même « iconv ... » [pour convertir les caractères en UTF8]) donc tout est ramené sur une seule ligne, ensuite il exécute un script sed avec « sed -r -f nom_du_script » et rétablit les retours à la ligne avec « tr '%' '\n' ».
Je souhaite en ce moment supprimé tous les commentaires (donc les balises commentaires) mais il y a des contraintes :
* comme tout est sur une seule ligne, il peut y avoir plusieurs commentaires donc la syntaxe « s|<!--.*-->||g » ne convient pas (par ex « 1<!--2-->3<!--4-->5 » deviendra « 15 » et non pas « 135 que je voudrais » !!),
* de plus le commentaire peut contenir des balises html (xml) donc la syntaxe suivante ne convient pas non plus : « s|<!--[^>]*-->||g » (car par ex : « <!-- 1<b>2</b> 3--> » ne se suppr correctement !!).
Donc voici un exemple concret je souhaite transformer ceci
<!--blabla1--> blabla2 <!-- bla<qcq>bla</qcq>--> blabla3
en ceci
blabla2 blabla3
Hors ligne
#17 Le 29/12/2009, à 12:23
- Totor
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Puisque tu tiens à n'avoir q'une seule ligne :
sed 's/-->/@/g; :deb ; s/<!--[^@]*@\(.*\)/\1/1; s/<!--/&/1; t deb'
Dernière modification par Totor (Le 29/12/2009, à 12:25)
-- Lucid Lynx --
Hors ligne
#18 Le 29/12/2009, à 15:41
- YvanD
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Je pense que mon seul pb est la syntaxe correcte pour dire à sed de s'arrêter à la prochaine expression (notamment dans mon cas : « --> »).
Je connais la syntaxe pour dire de s'arrêter au prochain caractère ("<!--[^>]*-->", mais comme je l'ai dit cela ne me convient pas).
Dernière modification par YvanD (Le 29/12/2009, à 15:41)
Hors ligne
#19 Le 29/12/2009, à 18:05
- YvanD
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Désolé je n'avais pas vu ton post Totor, merci.
Je n'avais pas penser à réduire --> à un seul caractère pour contourner mon problème !
Si quelqu'un à mieux... en attendant je met en résolu.
Dernière modification par YvanD (Le 29/12/2009, à 18:06)
Hors ligne
#20 Le 29/12/2009, à 19:04
- Balkoth
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Version qui fonctionne même si le commentaire contient des @ :
sed -r 's/<!--([^-]|-[^-]|--[^->])*-+->//g'
Hors ligne
#21 Le 30/12/2009, à 23:06
- Pylades
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Pour réduire le fichier à une ligne, voici une commande fonctionnant même si le fichier source contient un % :
[code]sed 's/$/
“Any if-statement is a goto. As are all structured loops.
“And sometimes structure is good. When it’s good, you should use it.
“And sometimes structure is _bad_, and gets into the way, and using a goto is just much clearer.”
Linus Torvalds – 12 janvier 2003
Hors ligne
#22 Le 30/12/2009, à 23:09
- Pylades
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Deuxième essai :
Pour réduire le fichier à une ligne, voici une commande fonctionnant même si le fichier source contient un % :
sed 's/$/le-caractère-unicode-F0000/g' | tr '\n' ' '
# Pour remettre les nouvelles lignes :
sed 's/le-caractère-unicode-F0000-suivit-d-un-espace/\n/g'
Ensuite, pour tes commentaires :
sed -r 's/<!--[^\(->\)]*->//g'
“Any if-statement is a goto. As are all structured loops.
“And sometimes structure is good. When it’s good, you should use it.
“And sometimes structure is _bad_, and gets into the way, and using a goto is just much clearer.”
Linus Torvalds – 12 janvier 2003
Hors ligne
#23 Le 30/12/2009, à 23:51
- Totor
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
sed -r 's/<!--[^\(->\)]*->//g'
Merci, je note !
(je passerai cette fin d'année moins bête )
-- Lucid Lynx --
Hors ligne
#24 Le 31/12/2009, à 11:00
- YvanD
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
Avec la méthode de Paul0102 ceci ne marche pas avec mon ex (plus haut) :
echo '<!--blabla1--> blabla2 <!-- bla<qcq>bla</qcq>--> blabla3' | sed -r 's/<!--[^\(->\)]*->//g'
Pourquoi ceci
sed -r 's/<!--[^\(->\)]*->//g'
alors qu'un commentaire (x)html se termine par « --> » et non pas « -> » ?
Enfin pourquoi avec --> ceci ne marche pas, ex :
$ echo '<!--blabla1--> blabla2 <!-- bla<qcq>bla</qcq>--> blabla3' | sed -r 's/<!--[^\(-->\)]*-->//g'
sed: -e expression n°1, caractère 23: Fin d'intervalle invalide
Dernière modification par YvanD (Le 31/12/2009, à 11:01)
Hors ligne
#25 Le 31/12/2009, à 12:20
- sputnick
Re : [Résolu] Sed : comment s'arrêter à la 1ère expression trouvée
C'est quoi le bins avec [^\(-->\)] ? ( Traduction en language humain si possible... )
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne