Avatar billede rrm Nybegynder
22. oktober 2007 - 20:52 Der er 17 kommentarer og
1 løsning

Regulære udtryk og finde mønster i strenge

Hejsa

Jeg sidder og med noget pcre, der kan finde og hente mønstre i en streng. Helt præcis er det:

streng = "<html>hlhtmlfsdfd<html>htmlgkjdfhgkjhdf<head><body></body></html>"

og her har jeg forsøgt med "(<|</)html>", uden dog at få meget andet end:
0 <html>
1 <

Den kode jeg bruger er

const char *error;
    const char *res;
  int  erroffset;
  pcre *re;
  int  rc;
  int oVecNeed;
    int* ovector;
    int      resLength;

    re = pcre_compile (
        pattern.c_str(),      /* the pattern *///
        0,                    /* default options */
        &error,              /* for error message */
        &erroffset,          /* for error offset */
        0);
   
    if (!re)
    {
        string tmp(error);
        errorMsg = "Internal error: pcre_compile failed with the error: " + tmp;
        errorMsg += " at " + intToStr(erroffset) + ":\n";
        errorMsg += pattern;
       
        return false;
    }

    if(pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &oVecNeed) != 0)
    {
        errorMsg = "Regular expression did not match any substring";
        return false;
    }

    ovector = new int[3*(oVecNeed+1)];

    rc = pcre_exec (
                                    re,                  /* the compiled pattern */
                                    0,                    /* no extra data - pattern was not studied */
                                    str.c_str(),          /* the string to match */
                                    (int) str.length(),  /* the length of the string */
                                    0,                    /* start at offset 0 in the subject */
                                    0,                    /* default options */
                                    ovector,              /* output vector for substring information */
                                    3*(oVecNeed+1));            /* number of elements in the output vector */

    if (rc < 0)
    {
   
        int errVal = 0;

        switch (rc)
        {
          case PCRE_ERROR_NOMATCH:
                errorMsg = "Regular expression did not match any substring";
                break;
          default:
                errorMsg = "Internal error: pcre_exec failed";
                break;
        }
   
        delete ovector;
        return false;
    }

    for (int i = 0; i < rc; i++) {
    printf("%2d: %.*s\n", i, ovector[2*i+1] - ovector[2*i], str.c_str() + ovector[2*i]);
  }

Er jeg helt ude i hamppen, eller kan nogen se hvorfor det ikke virker???
Avatar billede arne_v Ekspert
22. oktober 2007 - 21:09 #1
Det virker vel fint.

<html> er total match (group 0)
< er match group 1

Men du vil nok noget andet.

Jeg kan finde et par eksempler.
Avatar billede arne_v Ekspert
22. oktober 2007 - 21:10 #2
#include <stdio.h>
#include <string.h>
#include <pcre.h>

void test(char *s)
{
    int ix;
    pcre *re;
    int rc;
    int erroffset;
    int ovector[300];
    const char *error;
    const char *p;
    re = pcre_compile("(?:<body>)(.*?)(?:</body>)",PCRE_CASELESS+PCRE_DOTALL+PCRE_MULTILINE,&error,&erroffset,NULL);
    rc = pcre_exec(re,NULL,s,strlen(s),0,0,ovector,sizeof(ovector)/sizeof(int));
    ix = 0;
    while((rc = pcre_exec(re,NULL,s,strlen(s),ix,0,ovector,sizeof(ovector)/sizeof(int)))>0)
    {
      pcre_get_substring(s,ovector,rc,1,&p);
      printf("%s\n",p);
      ix = ovector[1];
    }
}

int main()
{
    test("<body>1</body>");
    test("<body>1</body><body>2</body>");
    test("<body>1</body><body>2</body><body>3</body>");
    return 0;
}
Avatar billede arne_v Ekspert
22. oktober 2007 - 21:11 #3
#include <stdio.h>
#include <string.h>
#include <pcre.h>

void test(char *s)
{
    int ix;
    pcre *re;
    int rc;
    int erroffset;
    int ovector[300];
    const char *error;
    const char *p;
    re = pcre_compile("[0-9]+",0,&error,&erroffset,NULL);
    ix = 0;
    while((rc = pcre_exec(re,NULL,s,strlen(s),ix,0,ovector,sizeof(ovector)/sizeof(int)))>0)
    {
      pcre_get_substring(s,ovector,rc,0,&p);
      printf("%s\n",p);
      ix = ovector[1];
    }
}

int main()
{
    test("abc 123 def 456 ghi 789 xyz");
    return 0;
}
Avatar billede nielle Nybegynder
22. oktober 2007 - 21:12 #4
En meget lille sidebemærkning, brug i stedet dette patteren:

"</?html>"
Avatar billede rrm Nybegynder
22. oktober 2007 - 23:20 #5
Dvs at man skal blive ved med at bruge pcre_exec, for at finde næste match??? Hvad  er det 4 argument til pcre_get_substring så???
Avatar billede rrm Nybegynder
23. oktober 2007 - 00:04 #6
Men hvordan er denne nemste måde at parse vilkårlige html tags??? Jeg har prøvet med </?.+>|<.+/?>, men ser ikke ud til at finde disse...
Avatar billede rrm Nybegynder
23. oktober 2007 - 00:22 #7
eller bare til <a...> og <img.../> tags??
Avatar billede arne_v Ekspert
23. oktober 2007 - 00:44 #8
Det er group number.

"abc" matched mod regex (a)(b)(c)

giver:
"abc" i gruppe 0
"a" i gruppe 1
"b" i gruppe 2
"c" i gruppe 3
Avatar billede arne_v Ekspert
23. oktober 2007 - 00:45 #9
"<[^>]*>"

måske
Avatar billede rrm Nybegynder
23. oktober 2007 - 13:25 #10
Tak arne, men jeg kan ikke lige gennemskue hvorfor <[^>]*> virker???

Skal det forstås sådan at først matcher den < og så er der et match for hver gang den møder et >???
Avatar billede arne_v Ekspert
23. oktober 2007 - 15:15 #11
< er bare en enkelte <
[^>]* er et antal af alt andet end >
> er bare en enkelt >
Avatar billede rrm Nybegynder
23. oktober 2007 - 15:20 #12
Ok, hvis man læser her http://perldoc.perl.org/perlre.html, så får jeg at ^ matcher i starten af strengen.....
Avatar billede arne_v Ekspert
23. oktober 2007 - 15:25 #13
Det er kun hvis det er udenfor []

:-)
Avatar billede rrm Nybegynder
23. oktober 2007 - 18:10 #14
hehe ok...Dvs den betyder not inde i []???
Avatar billede arne_v Ekspert
23. oktober 2007 - 18:11 #15
Jeps.
Avatar billede rrm Nybegynder
23. oktober 2007 - 18:35 #16
ok.... :) Men lig et svar og tak for hjælpen
Avatar billede nielle Nybegynder
23. oktober 2007 - 18:44 #17
23/10-2007 18:10:38> Kun hvis den er lige efter den indlefdende '[' :

[abc] = matcher et vilkårligt tegn som er enten et 'a', et 'b' eller et 'c'.
[^abc = matcher et vilkårligt tegn som hverken er et 'a', et 'b' eller et 'c'.

Den helt korte form som arne_v bruger:

[^>]

skal altså læses som:

matcher et vilkårligt tegn som ikke er et '>'.
Avatar billede arne_v Ekspert
23. oktober 2007 - 18:51 #18
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester



IT-JOB

MAN Energy Solutions

Department Manager Edge Platform

DEIF A/S

DevOps Engineer

PensionDanmark

ML Engineer

Fælles Hjælpemiddeldepot I/S

Projektleder til nytænkende ERP-projekt

Københavns Erhvervsakademi

IT-supporter elev