Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C++] Regexp gebaseerd op PCRE werkt niet

Pagina: 1
Acties:

  • evolution536
  • Registratie: Maart 2009
  • Laatst online: 05-06-2024
Ik ben een tijdje bezig met een Regular Expression die URL's uit een stuk HTML text moet filteren. Ik gebruik hiervoor de Ultimate++ library waar ook een regexp in zit. Deze is gebaseerd op PCRE. Echter zijn er een aantal regexp's waar ik niet uit kom. Ze werken niet en ik kan maar niet vinden waarom. De documentatie van PCRE heeft me niet verder kunnen helpen. De code is als volgt.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Vector<ImdbLink> ImdbManager::ParseResultPage(String pText)
{
    RegExp mRexp("(<p><b>.*?)\n"); // werkt wel!
    String mSection;
    Vector<ImdbLink> mLinks;
    if (mRexp.Match(pText))
    {
        mSection = mRexp[0];
    }
    if (mSection.Find("<b>Popular Titles</b>") != -1)
    {
        String mLine = mRexp[0];
        mRexp.SetPattern("(<a href=.*?)</td></tr>"); // werkt niet!
        if (mRexp.Match(mLine))
        {
            for (int i = 0; i < mRexp.GetCount(); i++)
            {
                CleanText(mLine);
                mRexp.SetPattern("<a href=""(.{17})"); // werkt niet omdat de bovenste ook niet werkt!
                if (mRexp.Match(mLine))
                {
                    mLinks.Add(mRexp[0]);
                }
            }
        }
    }
    return mLinks;
}


Kan iemand me met dit probleem helpen?

  • Miyamoto
  • Registratie: Februari 2009
  • Laatst online: 23-11 23:04
Wat is de input en wat is de gewenste output?
Heb je gekeken wat er door de eerste tag gematched wordt?

Je zoekt op een begin van de a, maar geen sluit-tag? Why?
Wat denk je te matchen in de tweede expressie? Werkt die wel op een input die je verwacht?

Ook de laatste is me niet duidelijk wat je daar wilt matchen.
En ook hier: Heb je deze 'los' getest, met de te verwachten input? Klopt dan de output?

Beetje debuggen...

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 20-11 11:59

NMe

Quia Ego Sic Dico.

Je expression is sowieso redelijk brak omdat je de twee makkelijk kan combineren. Wat je probleem betreft gok ik op een multiline-probleem. Zoek eens op wat de dotall modifier voor je kan betekenen.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:16

.oisyn

Moderator Devschuur®

Demotivational Speaker

Sowieso vind ik het erg vaag dat je binnen de for loop de mRexp expressie aan zit te passen waar je in de conditie van de loop weer op test. Ik snap je code sowieso niet overigens, je doet verder ook niets met de matches.

[ Voor 22% gewijzigd door .oisyn op 30-10-2012 14:01 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • evolution536
  • Registratie: Maart 2009
  • Laatst online: 05-06-2024
.oisyn schreef op dinsdag 30 oktober 2012 @ 14:00:
Sowieso vind ik het erg vaag dat je binnen de for loop de mRexp expressie aan zit te passen waar je in de conditie van de loop weer op test. Ik snap je code sowieso niet overigens, je doet verder ook niets met de matches.
Hier doe ik iets met de match.

C++:
1
mLinks.Add(mRexp[0]); 


Daarnaast verander ik het pattern omdat ik niet meerdere RegExp objecten wil aanmaken. Het aanpassen van het pattern werkt echter prima, dit veranderd niets aan de waarden in het array op dat moment.

Het gaat om een resultaatpagina van de IMDb. Deze link geeft zon pagina. http://www.imdb.com/find?q=<trefwoord>&s=tt

Uit die pagina krijg je blokken van resultaten. Dit zijn bijv. "Popular Titles", "Exact Matches", etc. In die blokken staan links. de href="" waarde die in die links staan wil ik eruit filteren. Ik probeer een bestaande IMDb API te porten naar C++. De bestaande is een C# project waarin de RegExp heel anders werkt.

De eerste RegExp haalt prima het blok Popular Titles eruit. Daarin zitten een aantal links die er niet uit worden gefilterd. Ik heb het uitvoerig gedebugged, maar de functie mRexp.Match() geeft een bool terug. Ik kan hier verder niets mee doen.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Wat zou ".*?" moeten doen?

Verder, C++ plakt aangrenzende strings aan elkaar. "<a href=""(.{17})" is hetzelfde als "<a href=" "(.{17})" of "<a href=(.{17})"

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 20-11 11:59

NMe

Quia Ego Sic Dico.

evolution536 schreef op dinsdag 30 oktober 2012 @ 14:36:
[...]

Hier doe ik iets met de match.

C++:
1
mLinks.Add(mRexp[0]); 


Daarnaast verander ik het pattern omdat ik niet meerdere RegExp objecten wil aanmaken. Het aanpassen van het pattern werkt echter prima, dit veranderd niets aan de waarden in het array op dat moment.
Fijn, maar je overschrijft dus je regexp-object op een plek in een loop die óók gebruik maakt van datzelfde object. Zelfs als je je regexp zo schrijft dat hij werkt, dan zul je alleen de eerste match vinden en daarna niets meer omdat je geen tweede object gebruikt en dus je loop "kwijtraakt". Schrijf liever je regular expression zo dat je er maar één nodig hebt.

Had je nou die dotall al opgezocht?

[ Voor 3% gewijzigd door NMe op 30-10-2012 15:03 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Hier kan ik maar 1 iets op zeggen eigenlijk:
http://regex.info/blog/2006-09-15/247

En om dan ook constructief te werken:
is het geen optie om een HTML parser (er zullen er wel talrijke te vinden zijn) te gebruiken om dit probleem op te lossen? Als de HTML bovendien valid XML is (en niet dat samenraapsel tags wat door IE6 gerenderd kon worden) dan kun je met een simpele XML parser ook uit de voeten. Je moet er dan trouwens geeneens veel moeite voor doen; met een SAX parser (bvb expat of xerces) kom je voor jouw doel een heel eind.

ASSUME makes an ASS out of U and ME


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:16

.oisyn

Moderator Devschuur®

Demotivational Speaker

evolution536 schreef op dinsdag 30 oktober 2012 @ 14:36:
[...]


Hier doe ik iets met de match.

C++:
1
mLinks.Add(mRexp[0]); 


Daarnaast verander ik het pattern omdat ik niet meerdere RegExp objecten wil aanmaken. Het aanpassen van het pattern werkt echter prima, dit veranderd niets aan de waarden in het array op dat moment.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
        mRexp.SetPattern("(<a href=.*?)</td></tr>");
        if (mRexp.Match(mLine))  // hier match je met bovenstaande pattern
        { 
            for (int i = 0; i < mRexp.GetCount(); i++)  // hier loop je over alle gevonden matches
            { 
                CleanText(mLine); 
                mRexp.SetPattern("<a href=""(.{17})"); // hier overschrijf je je regex met een ander pattern
                if (mRexp.Match(mLine)) 
                { 
                    mLinks.Add(mRexp[0]); // hier doe je iets met de match van regel 8
                } 
            }  // bij de volgende iteratie van deze loop zijn je oude matches van regel 2 dus verdwenen, omdat je op regel 8 opnieuw hebt gematcht
        } 


Wellicht realiseer je je niet dat mRexp.GetCount() bij iedere iteratie opnieuw wordt aangeroepen. Als de buitenste regex 10 keer matcht, maar de binnenste regex maar 1 keer, dan zal de for lus maar 1 keer itereren omdat hij voor de tweede iteratie test of i < mRexp.GetCount(), oftewel 1 < 1, en dat is false, en dus stopt ie.

Bovendien doe je niets daadwerkelijk met matches van regel 2. Stel je zou daadwerkelijk 10 keer itereren, dan doe je dus 10 keer hetzelfde want mLine wordt niet aangepast in tussentijd. Ik zou een mRexp[i] verwachten ergens voordat je mRexp een nieuwe pattern geeft op regel 8, maar die zie ik niet.

[ Voor 44% gewijzigd door .oisyn op 30-10-2012 19:29 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:16

.oisyn

Moderator Devschuur®

Demotivational Speaker

Was dit nog opgelost?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • evolution536
  • Registratie: Maart 2009
  • Laatst online: 05-06-2024
Ik ben hier nog steeds naar aan het kijken. Echter kan de thread wat mij betreft worden gesloten aangezien ik van PCRE overgegaan ben naar de C++ 11 regex. Ik ben erg bezig met kijken hoe de code anders kan omdat ik er na jullie reacties van overtuigd ben dat mijn code beter moet/kan. Er zijn meerdere oplossingen voor dit probleem en ik denk dat ik met een andere oplossing beter af ben.

In ieder geval bedankt voor jullie reacties! Ik ben er in kennis van C++ in ieder geval zeker wijzer van geworden.

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Nog een waarschuwing ter overweging:
Parsing HTML with regex summons tainted souls into the realm of the living. [...] If you parse HTML with regex you are giving in to Them and their blasphemous ways which doom us all to inhuman toil for the One whose Name cannot be expressed in the Basic Multilingual Plane, he comes.
;)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


  • evolution536
  • Registratie: Maart 2009
  • Laatst online: 05-06-2024
Ik heb mijn probleem op de volgende manier opgelost:

C++:
1
2
3
4
5
6
7
8
9
10
regex mRexp("<a href=\"(.{17})\"");
    Vector<ImdbLink> mLinks;
    string pTextTemp(pText);
    const tr1::sregex_token_iterator end;
    for (tr1::sregex_token_iterator i(pTextTemp.begin(), pTextTemp.end(), mRexp);
        i != end; i++)
    {
        mLinks.Add((*i).str());
    }
    return mLinks;
Pagina: 1