[PHP] Begrippen vervangen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik zit met het volgende. Ik ben bezig met een UBB parser en deze heeft onder andere de mogelijkheid voor het vervangen van begrippen. Stel dat je de tekst "dit is een tekst" hebt en tekst is een begrip dan wordt de uitvoer "dit is een <a href="#begrip">tekst</a>. Lijkt me duidelijk :D

Het probleem komt pas wanneer iemand een link aanmaakt met de [url] tag en er binnen de tekst van de link een begrip voorkomt. Bijvoorbeeld [url=a]tekst[/url].

In de eerste iteratie zou dit dus worden: <a href="a">tekst voorbeeld</a>.

Wanneer ik de begrippen vervang krijg je dus: <a href="a"><a href="#begrip">tekst</a> voorbeeld</a> en dit snapt de browser niet :)

Het is vast mogelijk om een regex in elkaar te bouwen die:

- Case insensitive is
- Betrekkelijk snel is (hoef geen parsetimes van meerdere secondes :P)
- Rekening houdt het feit dat er geen begrippen voor mogen komen in [img] en [url] tags

Zoals gezegt, deze regex is er vast maar ik kan hem niet bedenken :P. Is er iemand die me een duwtje in de juiste richting kan geven?

[ Voor 8% gewijzigd door Verwijderd op 03-05-2006 11:40 ]


Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

AFAIK kan dit niet goed werken met regexps. Je kan beter kijken naar de mogelijkheden van een simpele stackbased parser. :)

'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

Ik zou het niet met regex proberen op te lossen, maar het hele zaakje in een boom hangen. Zodoende kun je textnodes die geen onderdeel zijn van een link node onderzoeken op eventuele begrippen.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hrmm, niet echt het antwoord waar ik op gehoopt had. Het idee was al bij me te binnen geschoten.
Ik kan me echter niet voorstellen dat ik met een stackbased parser de toch tamelijk grote berichten kan verwerken waarbij ik rekening moet houden 800+ begrippen zonder dat die parsetimes van secondes voorbij komen :)

Is er niet zoiets mogelijk als:
Vervang string die NIET begint met [url=(.*)] of [img=(.*)]en die NIET eindigd met [/url] of[/img]

Acties:
  • 0 Henk 'm!

  • JHS
  • Registratie: Augustus 2003
  • Laatst online: 16-09 16:02

JHS

Splitting the thaum.

Buiten wat de heren voor mij zeggen zou je misschien kunnen kijken naar conditional subpatterns. Misschien zou zoiets kunnen werken:

code:
1
/(?:(?(?<[url[^\]]*])[/url]|.*))(tekst)/Usi


Het start met een conditional subpattern, welke voorafgegaan wordt door ?: om aan te geven dat het non-matching is. De conditie is een lookbehind assertation naar [url] met eventuele tekst ertussen. Als de conditie waar is, wordt er gezocht naar een sluittag voor de url. Anders wordt alles toegestaan. Vervolgens wordt er gematched op 'tekst'.

DM!


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
JHS schreef op woensdag 03 mei 2006 @ 12:06:
Buiten wat de heren voor mij zeggen zou je misschien kunnen kijken naar conditional subpatterns. Misschien zou zoiets kunnen werken:

code:
1
/(?:(?(?<[url[^\]]*])[/url]|.*))(tekst)/Usi


Het start met een conditional subpattern, welke voorafgegaan wordt door ?: om aan te geven dat het non-matching is. De conditie is een lookbehind assertation naar [url] met eventuele tekst ertussen. Als de conditie waar is, wordt er gezocht naar een sluittag voor de url. Anders wordt alles toegestaan. Vervolgens wordt er gematched op 'tekst'.
Okee, ik geloof meteen dat het de oplossing is alleen snap ik er de ballen van :P.
En omdat ik de regex zal moeten uitbreiden i.v.m. de [img] tag ( de [imgc], [imgcb] enz.) dan zal ik hem toch aan moeten passen. Vandaar de vraag, zou je dit toe kunnen lichten? Ik zou je eeuwig dankbaar zijn :P

Acties:
  • 0 Henk 'm!

  • JHS
  • Registratie: Augustus 2003
  • Laatst online: 16-09 16:02

JHS

Splitting the thaum.

Ik heb hem hierboven al redelijk uitgelegd, zie verder ook deze pagina :) . Maar hierbij toch wat uitgebreidere uitleg:

code:
1
/.../Usi

Als eerste willen we graag dat we ungreedy matchen, vandaar de U. Anders zouden we een url tag kunnen matchen met de sluittag aan het eind, terwijl er in het midden ook een staat. Verder willen we dat we over meerdere newlines heen kunnen matchen, vandaar de s. Ook willen we dat [URL] of TEXT matchen, dus case-insensitive, dus i.

code:
1
/(?:...)(tekst)/Usi

We gaan eerst testen, en vervolgens pas matchen, namelijk op het begrip dat je wil vervangen. De ?: geeft aan dat waar we op gaan testen niet meematched.

code:
1
(?:(?(...)...|...))(tekst)/Usi

Onze test is een conditional subpattern. Afhankelijk van een bepaalde conditie gaan we de een, of de andere match uitvoeren. Dit omdat we alleen in het geval van een openingstag willen controlleren of er een sluittag is.


code:
1
(?:(?(?<\\[url[^\]]*])...|...))(tekst)/Usi

De conditie is een lookbehind assertation. We gaan matchen op de sluittag, maar alleen als deze voorafgegaan werd door een url tag. Een url tag bestaat uit [url, gevolgd door alles behalve een ], gevolgd door een ]. De character group [^\]]* zorgt daarvoor.

code:
1
/(?:(?(?<\\[url[^\]]*])\\[/url\]|.*))(tekst)/Usi

Als de conditie waar is matchen we op [url], waarbij we niet moeten vergeten de [ en ] te escapen (was ik hierboven we vergeten). Anders matchen we op alles, in elke hoeveelheid.

Als je dit wil toepassen met eerdere tags moet je (?:...|...) gebruiken, wat alternatieve branches, nonmatching, aangeeft. Je zou dan zoiets krijgen:
code:
1
/(?:(?(?<\\[(?:url|img|...)[^\]]*])\\[/(?:url|img|...)\]|.*))(tekst)/Usi

Dat levert het echter het probleem op dat img gezien wordt als valide sluittag van url. Misschien valt dat met recursieve patterns nog op te lossen, maar ik kan niet direct zien hoe. Bovendien: áls mijn techniek al werkt, levert het zeer waarschijnlijk problemen op met invalide syntaxes. Ook zou je bij het matchen van enige tag moeten controleren op het gesloten zijn van andere tags. Je kan dus geen tags gaan nesten, anders zou `[url] ... [img]...[/img] begrip` alsnog problemen opleveren.

[ Voor 5% gewijzigd door JHS op 03-05-2006 12:31 ]

DM!


Acties:
  • 0 Henk 'm!

  • mcdronkz
  • Registratie: Oktober 2003
  • Laatst online: 16-04 12:44
Het zal wel niet optimaal zijn, maar ik heb dit gedaan;

PHP:
1
2
3
4
5
6
7
8
//begrippen
    $sql = mysql_query("SELECT * FROM begrippen");
    while($result = mysql_fetch_array($sql)) {
        $begrippen[] = $result['begrip'];
        $content[] = "<span class=\"begrip\"><a href=\"?p=begrippen&begrip=".$result['begrip']."\">" . $result['begrip'] . "</a></span>";
    }
    
    $input = str_replace($begrippen,$content,$input);


Sorry, zie dat jij met een heel ander probleem zit !

[ Voor 64% gewijzigd door mcdronkz op 03-05-2006 12:34 ]


Acties:
  • 0 Henk 'm!

  • JHS
  • Registratie: Augustus 2003
  • Laatst online: 16-09 16:02

JHS

Splitting the thaum.

mcdronkz: Dat lost toch geenszins het probleem van de TS op, namelijk het voorkomen van geneste anchors (bijvoorbeeld) :? .

DM!


Acties:
  • 0 Henk 'm!

  • mcdronkz
  • Registratie: Oktober 2003
  • Laatst online: 16-04 12:44
JHS schreef op woensdag 03 mei 2006 @ 12:34:
mcdronkz: Dat lost toch geenszins het probleem van de TS op, namelijk het voorkomen van geneste anchors (bijvoorbeeld) :? .
Mijn fout, had te vluchtig gekeken ;).

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op woensdag 03 mei 2006 @ 12:05:
Hrmm, niet echt het antwoord waar ik op gehoopt had. Het idee was al bij me te binnen geschoten.
Ik kan me echter niet voorstellen dat ik met een stackbased parser de toch tamelijk grote berichten kan verwerken waarbij ik rekening moet houden 800+ begrippen zonder dat die parsetimes van secondes voorbij komen :)
Ik denk dat je stack-based juist performance winst gaat behalen ten opzichte van regex. Het lijkt me dan ook een veel logischere oplossing. Tevens kun je veel makkelijker de integriteit van de tags waarborgen en van daaruit acties ondernemen, want je hebt immers een volledig path tot je beschikking.

Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

Ter indicatie: RML ("BB-code") wordt op GoT ook stackbased geparset. ;)

'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

Topicstarter
Ja, maar das niet realtime ;)
De oplossing wordt dus waarschijnlijk een stackbased parser met een cache tabel.
Dan is het wel niet realtime meer maar is de snelheid iig wel te harden :P.

[ Voor 74% gewijzigd door Verwijderd op 04-05-2006 00:36 ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Verwijderd schreef op donderdag 04 mei 2006 @ 00:35:
Ja, maar das niet realtime ;)
De oplossing wordt dus waarschijnlijk een stackbased parser met een cache tabel.
Dan is het wel niet realtime meer maar is de snelheid iig wel te harden :P.
Stackbased gaat je zeker performancewinst opleveren en is minder foutgevoelig dan complexe regexps.

Overigens zou ik de begrippen cachen in een soort van hashmap en ipv voor elk begrip te kijken of die in de content voorkomt de omgekeerde approach kiezen: je content opslitsen in woorden en voor elk woord kijken of het een begrip is. Zeker in een stackbased situatie heb je vaak met meerdere vrij korte stukken tekst te maken.

Intentionally left blank

Pagina: 1