[rex.exp.][php] greediness kwestie

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ben bezig met een zoekfuntie (PHP) die de gevonden woorden highlight.
Dit gaat uitstekend, echter zit er een schoonheidsfout in die ik met mijn kennis en zoekvaardigheden niet op kan lossen.

Ik heb het navolgende.

code:
1
/([>]{1}.*[\.]*[><]{0})(zoekwoord)(.*[\.]*[><]{0}[<]{1})/i


Met behulp van preg_replace_callback() vervang is nu $match[1] door een bold(HTML)-versie van $match[1].

Geen probleem, werkt uitstekend. Hij vervangt alle matches netjes zolang die niet binnen een HTML tag staan (dit wordt gecontrolleerd in de reguliere expressie).
Echter gaat het mis met de greediness.

Als ik een input als dit geef:

code:
1
<font|><b class="zoekwoord">zoekwoord<|/b></font>


Dan ziet hij de string tussen de '|' als match. Logischerwijs.
Heeft iemand een idee hoe ik dat op kan vangen?

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Greedyness is over het algemeen op te lossen door .*? te gebruiken in plaats van .*

Ik heb momenteel niet echt tijd om het uit te typen, maar misschien kun je met deze hint al wat?

'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.


Acties:
  • 0 Henk 'm!

Verwijderd

Misschien helpt het als je HTML tags matcht op een andere manier. Voorbeeld:

code:
1
|^(?:<[^>]+>)* [^<]* (zoekwoord)|xi


Macht bij (goedgevormde) HTML de eerste keer dat `zoekwoord' voorkomt buiten een HTML tag. Nadeel van deze regex is dat hij maar 1 keer matcht, dus deze moet je herhaaldelijk uitvoeren tot er niets meer verandert. Dat hoeft niet zo'n grote performance bottleneck te zijn als je 'm eerst compileert.

En om je oorspronkelijke vraag te beantwoorden:

code:
1
|...regex...|U


maakt de regex Ungreedy.

[ Voor 4% gewijzigd door Verwijderd op 08-10-2004 17:28 ]


Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

OneOfBorg:
Misschien helpt het als je HTML tags matcht op een andere manier. Voorbeeld:

code:
1
|^(?:<[^>]+>)* [^<]* (zoekwoord)|xi
Die gaat niet werken. Die matcht namelijk alleen als er direct achter een > het zoekwoord staat. De [^<]* heeft verder geen invloed, want een karakter kan niet en een < en de eerste letter van het zoekwoord zijn.

Overigens is dit al heel vaak voorgekomen en ik heb daarbij al vaker aangeraden dat het vele malen eenvoudiger is om eerste de content te splitten op html tags en daarna de highlight uit te voeren.

Zie o.a. [rml]drm in "[ PHP] gezochte woorden een kleur geven"[/rml]

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

Verwijderd

drm schreef op 08 oktober 2004 @ 20:50:
Die gaat niet werken. Die matcht namelijk alleen als er direct achter een > het zoekwoord staat. De [^<]* heeft verder geen invloed, want een karakter kan niet en een < en de eerste letter van het zoekwoord zijn.
Bzzt. You are not a winner.

De [^<]* zorgt er voor dat een willekeurig aantal karakters gematcht wordt tot het begin van het zoekwoord, maar dat niet ondertussen nog een HTML tag geopend wordt.

Python:
1
2
3
>>> from re import *
>>> sub('^((?:<[^>]+>)*[^<]*)(zoekwoord)', '\\1vervangen woord!', '<blaat>het zoekwoord</blaat>')
'<blaat>het vervangen woord!</blaat>'


Edit: Misschien dacht je dat ik lookahead/lookback constructies aan het gebruiken was. Dat is niet zo; ?: maakt een niet-refereerbare groep aan.

[ Voor 19% gewijzigd door Verwijderd op 10-10-2004 17:49 ]


Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

OneOfBorg:
Bzzt. You are not a winner.

De [^<]* zorgt er voor dat een willekeurig aantal karakters gematcht wordt tot het begin van het zoekwoord, maar dat niet ondertussen nog een HTML tag geopend wordt.
Hmja, zit wat in 8)7
Edit: Misschien dacht je dat ik lookahead/lookback constructies aan het gebruiken was. Dat is niet zo; ?: maakt een niet-refereerbare groep aan.
Neuh, ik maakte even een rare gedachtenkronkel... :)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Hou btw rekening met overlap van zoekwoorden. (Als je meerdere tegelijk kan zoeken.) Want dan wil je nog wel eens problemen mee krijgen. :)

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • Skaah
  • Registratie: Juni 2001
  • Laatst online: 16-09 18:38
Grijze Vos schreef op 11 oktober 2004 @ 02:10:
Hou btw rekening met overlap van zoekwoorden. (Als je meerdere tegelijk kan zoeken.) Want dan wil je nog wel eens problemen mee krijgen. :)
Dat is makkelijk op te lossen door bij het highlighten alleen te matchen wanneer een zoekwoord een boundary bevat: regexp: \bwoord\b (wel: woord, niet voorwoord).
Pagina: 1