Forum Programmation.autre Question sed

Posté par .
Tags : aucun
2
28
jan.
2009
J'utilise sed depuis pas mal de temps mais des détails m'échappent.
Aujourd'hui je bloque sur un truc tout simple et les tutoriaux et pages de manuels ne m'aident pas.

J'ai du code html dont je veux extraire une adresse ip. Voici les 3 lignes qui m'interessent:

td width="40%" class = "br_tb">prints(m_IPaddr); :
td colspan=2 class = "bl_tb" > 
(TAB)(TAB)(TAB)117.18.244.113

Je ne mets pas les '<' car l'affichage devient incomplet (?!). C'est sans importance pour l'exemple.

Je souhaite utiliser "prints(m_IPaddr)" pour détecter la zone à analyser (il y a dans ce code html plusieurs endroits contenant une adresse ip, mais seule la permière zone contient la valeur qui m'interesse).
Ensuite je saute 2 lignes, j'ai des tabulations (notées (TAB) dans mon exemple) puis j'ai l'adresse que je souhaite extraire.

Si j'utilise ça:

sed -n '/prints(m_IPaddr)/ {N;N; {s#^.*\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\)#\1#p}}' < fichier.html

J'obtiens 17.18.244.113 il manque le premier chiffre, pourtant sed est soit-disant greedy par défaut.

J'aimerais indiquer que le début de la ligne contient des tabulations ou des blancs. Alors j'utilise [ [ :blank:]]* ou [ \t]* mais ça ne donne rien:

sed -n '/prints(m_IPaddr)/ {N;N; {s#^[ \t]*\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\)#\1#p}}' < fichier.html
sortie=vide


Si j'indique les 3 tabulations, idem, je n'obtiens rien:

sed -n '/prints(m_IPaddr)/ {N;N; {s#^\t\t\t\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\)#\1#p}}' < fichier.html
sortie=vide


Si je ne mets pas le '^' alors ça m'affiche les 3 lignes. Je ne comprends pas pourquoi non plus (option -n pourtant).

Je sèche.
  • # espace et tab

    Posté par . Évalué à 2.

    espace et tabulation c'est :space: il me semble

    sinon perso pour generer une regexp j'utilise le petit logiciel txt2regex
  • # Read/Append

    Posté par . Évalué à 5.

    Pour le premier cas j'obtiens 7.18.244.113 ce qui n'est pas ce que tu recherches, mais est quand même beaucoup plus logique.

    J'arrive à faire fonctionner le deuxième et le troisième cas en remplaçant tes N majuscules par des n minuscules (ce qui d'après la doc signifie qu'on lit juste les lignes mais sans les analyser, ou quelque chose dans le genre)
    • [^] # Re: Read/Append

      Posté par . Évalué à 1.

      Pareil pour moi, je n'ai pas compris pourquoi j'ai 2 chiffres au lieu d'un, ce qui serait logique. Mais comme quelque chose m'échappe, la logique n'est probablement pas tout à fait la même.
  • # Réponse sed

    Posté par . Évalué à 4.

    cat test/gremous.txt
    td width="40%" class = "br_tb">prints(m_IPaddr); :
    td colspan=2 class = "bl_tb" >
    117.18.244.113

    sed -n '/prints(m_IPaddr)/N; N; s/.*\t\+\(\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\)$/\1/p' test/gremous.txt
    117.18.244.113
    • [^] # Re: Réponse sed

      Posté par . Évalué à 0.

      tiens ? les tabulations n'apparaîssent pas, mais elles sont bien dans test/gremous.txt.
      Donc, lisez :
      td width="40%" class = "br_tb">prints(m_IPaddr); :
      td colspan=2 class = "bl_tb" >
      tabtabtab117.18.244.113
    • [^] # Re: Réponse sed

      Posté par (page perso) . Évalué à 2.

      Oui, mais non : il faut tout mettre entre accolades...

      sed -nre '/prints\(m_IPaddr\)/{
        n;n # saute les deux lignes inutiles
        s/[ \t]+//g # supprime les espaces et tabulations
        /^[0-9]{1,3}(\.[0-9]{1,3}){3}$/p # écrit quand le reste ressemble à une IP
      }'
    • [^] # Re: Réponse sed

      Posté par . Évalué à 2.

      Malheureusement il y a plusieurs occurences qui apparaissent dans le fichier, donc cette solution ne fonctionne pas car ça affiche toutes les IP.
      • [^] # Re: Réponse sed

        Posté par (page perso) . Évalué à 1.

        Il y a trop de réponses parce que, sans accolades, seul le premier
        N dépend de la condition /prints(m_IPaddr)/ :
        sinon, le second N ajoute toujours la ligne suivante dans le tampon,
        et si sed y trouve une IP précédée d'une tabulation ...
  • # Greedy

    Posté par (page perso) . Évalué à 6.

    Justement, comme tu le dis, sed est greedy par défaut, ce qui veut dire que ton premier .* bouffe le maximum de caractères dont les premiers chiffres.
    • [^] # Re: Greedy

      Posté par . Évalué à 2.

      Très juste. Je me focalisais sur mon besoin.
      J'ai rectifié avec un [^0-9]. Merci :)
  • # La soluce

    Posté par . Évalué à 5.

    Merci à tous pour vos éclairages :)
    La solution est:
    '/prints(m_IPaddr)/ {N;N; s#.*[^0-9]\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\)#\1#p}'

    Ca fonctionne parfaitement, mais ce n'est pas 100% ce que je voulais puisque je n'arrive pas à faire s#^[ \t]*([0-9]\{1,3\}... (c'est à dire autoriser espaces et tabulations en début de ligne et rien d'autre). Si je fais ça, ça ne me retourne plus rien. Moi rien comprendre. Or j'aime bien comprendre :)
    • [^] # Re: La soluce

      Posté par . Évalué à 4.

      Remplace tes N;N; par des n;n; et cela fonctionnera.

      N concatène la ligne analysée avec la ligne suivante, alors que ce que tu désires, c'est passer à la ligne suivante, donc n minuscule. C'est parce que sed est vraiment un glouton que ta soluce semblait bonne.
      • [^] # Re: La soluce

        Posté par . Évalué à 1.

        Voilà LA réponse qui me fait comprendre pourquoi mes tests en début de ligne ne fonctionnaient pas. ffx en avait parlé plus haut mais ça ne m'avait pas interpellé.
        Merci :)

        La solution "vraie de vraie" est:
        '/prints(m_IPaddr)/ {n;n; s#^[ [:blank:] ]*\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\)[ [:space:] ]*#\1#p}'

        J'ai ajouté [ [:space:] ]* à la fin car j'ai un saut de ligne à la Microsoft.
        note pour Neox: [:space:] détecte les tabs horizontales et verticales, les espaces et les deux caratères de fin de ligne. [:blank:] détecte uniquement espaces et tabs horizontales.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.