IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

sed & regex: matcher 2 champs à la fois


Sujet :

Shell et commandes GNU

  1. #1
    Futur Membre du Club
    Homme Profil pro
    chercheur
    Inscrit en
    Janvier 2017
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Janvier 2017
    Messages : 8
    Points : 5
    Points
    5
    Par défaut sed & regex: matcher 2 champs à la fois
    Je cherche a extraire noms de fichier image + titres dans un gros fichier html.
    ( Ok ça serait faisable en autre chose que sed, mais j'y étais presque et ça m'interesse de comprendre anyway :-) )

    voici l'expression à laquelle je suis parvenu, sur une courte chaine d'exemple, mais ça ne marche pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo '(path/yac5cxfjm1.png)"></span><xxx><yyy>le titre</span>' | sed 's#/\([0-9a-z]*\).png)"></span>\([!>]*\)>\([!>]*\)>\([!<]*\)#@ FILE:\1 TITLE:\4/a%\n#g'
    visiblement le probleme se situe au premier '>':
    s#/\([0-9a-z]*\).png)"></span>\([!>]*\) matche mon exemple,
    mais pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    s#/\([0-9a-z]*\).png)"></span>\([!>]*\)>
    une idee du soucis ?
    (NB: c'est pas une question d'echappement de ! et > , j'ai déjà testé)
    NB: j'en suis venu a matcher explicitement chaque <...> entre mes 2 champs visés (nom et titre), parceque \(.*\) essayé auparavant semble faire un match maximaliste et non minimaliste.

    merci !

  2. #2
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 391
    Points
    19 391
    Par défaut
    BONJOUR !

    empiriquement j'en arrive à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ echo '(path/yac5cxfjm1.png)"></span><xxx><yyy>le titre</span>' | sed 's/.*\/\([^.]*\).png.*>\(.*\)<\/.*/\1 -- \2/'
    yac5cxfjm1 -- le titre
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    chercheur
    Inscrit en
    Janvier 2017
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Janvier 2017
    Messages : 8
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    empiriquement j'en arrive à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ echo '(path/yac5cxfjm1.png)"></span><xxx><yyy>le titre</span>' | sed 's/.*\/\([^.]*\).png.*>\(.*\)<\/.*/\1 -- \2/'
    yac5cxfjm1 -- le titre
    Certes, mais comme je disais, \(.*\) a une facheuse tendance a matcher a maxima, c'est a dire avec tout le reste du bloc.
    Donc dans le vrai contexte ou je dois reconnaitre toute une serie de nom + titre, ça ne marche plus :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo '(path/file1.png)"></span><xxx><yyy>le titre1</span><zzz><(path/file2.png)"></span><xxx><yyy>le titre2</span>' | sed 's/.*\/\([^.]*\).png.*>\(.*\)<\/.*/\1 -- \2/'g
    par ailleurs là j'ai simplifié les balises intermédiaires, mieux vaut donc vraiment reconnaire le fichier comme \/\([0-9a-z]*\).png pour matcher specifiquement.
    Mais ça ne change rien au 1er soucis avec \(.*\) . C'est bien pour ça que j'en suis venu spécifiquement a reconnaitre les 2 balises intermédiaires, a coup de "non '>'" puis '>'.

    Ce serait utile qu'on sache ce que tu veux obtenir.
    un site tiers a oublié de prévoir qu'on puisse vouloir faire des backup de nos fiches, ou en donner la liste des liens sur nos blogs. Mais il y a un menu généré dynamiquement qui les affiche. En sauvant le html (un gros bloc bien moche), on arrive facilement a reconnaitre les champs utiles (pour chaque entree de la liste, path vers la miniature de la fiche, reutilisable pour indexer la fiche elle meme, et titre). Ok, vouloir faire ça avec sed c'est bourrin par rapport a un parseur xml, mais j'y suis facilement arrivé sans la partie titre, et là je butte... et j'aimerais comprendre l'erreur conceptuelle, anyway :-)

  4. #4
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 861
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 861
    Points : 6 565
    Points
    6 565
    Par défaut
    En fait, tu te trompes sur le signe de négation d'une classe de caractère qui n'est pas le point d'exclamation mais l'accent circonflexe.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  5. #5
    Futur Membre du Club
    Homme Profil pro
    chercheur
    Inscrit en
    Janvier 2017
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Janvier 2017
    Messages : 8
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par CosmoKnacki Voir le message
    En fait, tu te trompes sur le signe de négation d'une classe de caractère qui n'est pas le point d'exclamation mais l'accent circonflexe.
    euh, oui (damned !!! ).

    mais j'ai toujours le probleme que ça n'embraye pas sur le second nom+titre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo '(path/yac5cxfjm1.png)"></span><xxx><yyy>le titre</span>' | sed 's#/\([0-9a-z]*\).png)"></span>\([^>]*\)>\([^>]*\)>\([^<]*\)#@ FILE:\1 TITLE:\4/a%\n#g'
    matche bien le premier set, mais appliqué à des données plus longues
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo '(path/nom1.png)"></span><xxx><yyy>le titre1</span><zzz>(path/nom2.png)"></span><xxx><yyy>le titre2</span><zzz>' | sed 's#/\([0-9a-z]*\).png ) "></span>\([^>]*\)>\([^>]*\)>\([^<]*\)#@ FILE:\1 TITLE:\4/a%\n#g'
    ça ne match plus rien du tout, ni le 1er ni le 2d set nom+titre.

  6. #6
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 391
    Points
    19 391
    Par défaut
    les données sont tronquées, tu devrais nous donner les vraies données (en remplaçant les informations personnelles, bien sûr), et en respectant le formatage.

    tout semble être sur une seule ligne, sed (pour le peu que je sache) ne va pas pouvoir réutiliser les mêmes références arrières pour chaque motif "fichier" et "titre", même avec le paramètre g.

    mais ce serait sûrement plus raisonnable, puisque c'est du XML, comme tu l'as dit, d'utiliser un parseur XML.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  7. #7
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 290
    Points : 12 759
    Points
    12 759
    Par défaut
    Bonjour,
    Voici un exemple certainement simplifiable, mais comme on ne sait pas vraiment la sortie que tu veux et que l'on a pas un vrai input, difficile de faire mieux:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ echo '(path/nom1.png)"></span><xxx><yyy>le titre1</span><zzz>(path/nom2.png)"></span><xxx><yyy>le titre2</span><zzz>'| sed 's#[^/]*/\([0-9a-z]*\)\.png\([^>]*><\)*[^>]*>\([^<]\+\)<[^(]*#@ FILE:\1 TITLE:\3/a%\n#g'
    @ FILE:nom1 TITLE:le titre1/a%
    @ FILE:nom2 TITLE:le titre2/a%
    Cordialement.

  8. #8
    Futur Membre du Club
    Homme Profil pro
    chercheur
    Inscrit en
    Janvier 2017
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Janvier 2017
    Messages : 8
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    les données sont tronquées, tu devrais nous donner les vraies données (en remplaçant les informations personnelles, bien sûr), et en respectant le formatage.tout semble être sur une seule ligne,
    il y en a pour des centaines de ko ! Voici une entree (ou se cachent 1 nom.png et un titre), il y en a plus d'une centaines concaténées comme ça sur une seule ligne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <div id="dcg-42526-495" class="saved-graph graph-link-container dcg-selected" ontap=""><div id="dcg-42526-496" role="link" tabindex="0" class="graph-link dcg-action-preview-graph"><span id="dcg-42526-497" class="dcg-thumb" style="background-image:url(https://s3.amazonaws.com/calc_thumbs/production/zstlwmmpkp.png)"></span><span id="dcg-42526-498" class="dcg-title"><span id="dcg-42526-499" class="">ship waves / Kelvin wake</span></span><span id="dcg-42526-500"> </span><span id="dcg-42526-501" class="date"><span id="dcg-42526-502" class="">yesterday</span></span></div><div id="dcg-42526-503" style="display: none"></div><div id="dcg-42526-504" style="display: none"></div><span id="dcg-42526-505" class="actions" handleevent="true"><span id="dcg-42526-506" role="button" tabindex="0" aria-label="Delete" class="dcg-icon-remove dcg-action-removegraph" ontap=""></span></span></div>
    Citation Envoyé par N_BaH Voir le message
    tout semble être sur une seule ligne, sed (pour le peu que je sache) ne va pas pouvoir réutiliser les mêmes références arrières pour chaque motif "fichier" et "titre", même avec le paramètre g.
    Je pense que si; par example ceci (qui isole juste file et le tag suivant) fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo '(path/nom1.png)"></span><xxx><yyy>le titre1</span><zzz>(path/nom2.png)"></span><xxx><yyy>le titre2</span><zzz>' | sed 's#/\([0-9a-z]*\).png)"><\([^>]*\)#@ FILE:\1 ITEM:\2%\n#g'
    ( bon je n'ai pas pipé avec les cut, mais les balises de repérage sont @ et %, juste avant le retour à la ligne inséré. )

  9. #9
    Futur Membre du Club
    Homme Profil pro
    chercheur
    Inscrit en
    Janvier 2017
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Janvier 2017
    Messages : 8
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Bonjour,
    Voici un exemple certainement simplifiable, mais comme on ne sait pas vraiment la sortie que tu veux et que l'on a pas un vrai input, difficile de faire mieux:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ echo '(path/nom1.png)"></span><xxx><yyy>le titre1</span><zzz>(path/nom2.png)"></span><xxx><yyy>le titre2</span><zzz>'| sed 's#[^/]*/\([0-9a-z]*\)\.png\([^>]*><\)*[^>]*>\([^<]\+\)<[^(]*#@ FILE:\1 TITLE:\3/a%\n#g'
    @ FILE:nom1 TITLE:le titre1/a%
    @ FILE:nom2 TITLE:le titre2/a%
    Hosanna, ça marche !!!
    Bon ben j'ai plus qu'à analyser caractère par caractère pourquoi le tient marche et pas le mien ;-) . Merci beaucoup !

    La ligne complete isolant la zone html utile, puis coupant proprement le resultat est donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cat saved.html | sed 's#>Examples</span></div>#\n\0\n#g' | sed -n '/>Examples<\/span><\/div>/q;p' | sed 's#[^/]*/\([0-9a-z]*\)\.png\([^>]*><\)*[^>]*>\([^<]\+\)<[^(]*#@ FILE:\1 TITLE:\3/a%\n#g' | cut -d'%' -f1 -s | cut -d'@' -f2 -s
    (une version + simple permet de lancer des wget de backup en rafale),

    et sa variante en produisant automatiquement une page web a partir de la liste:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cat saved.html | sed 's#>Examples</span></div>#\n\0\n#g' | sed -n '/>Examples<\/span><\/div>/q;p' | sed 's#[^/]*/\([0-9a-z]*\)\.png\([^>]*><\)*[^>]*>\([^<]\+\)<[^(]*#@<li><a href="https://www.desmos.com/calculator/\1"><img height="100px" src="https://s3.amazonaws.com/calc_thumbs/production/\1.png">\3</a>%\n#g' | cut -d'%' -f1 -s | cut -d'@' -f2 -s > myGraphs.html
    le résultat (encore brut de fonderie) est visualisé ici : http://evasion.imag.fr/~Fabrice.Neyr...osGraphs2.html

    Encore merci !
    (vraiment, même après ça, tu ne goute pas à cette beauté cabalisto-codegolfesque de sed ? :-) )

+ Répondre à la discussion
Cette discussion est résolue.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo