[PHP] De zoveelste regex noob

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Kaastosti
  • Registratie: Juni 2000
  • Laatst online: 22-09 17:13

Kaastosti

Vrolijkheid alom!

Topicstarter
Voordat iedereen nu meteen met tomaten begint te gooien en mij het forum uit-boeee't... ik heb echt m'n best gedaan. Wat ik probeer te doen is BB-coding uit de database van een phpBB forum om te zetten naar html. De syntax die wordt gebruikt in het forum zelf is de volgende:
PHP:
1
2
str_replace("[b:$uid]", $ietsanders, $bericht);
str_replace("[/b]", $ietsanders, $bericht);

Redelijk recht-toe-recht aan dus. Nu wil het geval dat ik deze omzetting eigenlijk in 1 keer wil doen en wel met een regular expression. Daarbij wordt er in de database voor $uid een hexidecimale waarde opgeslagen, maar wat die waarde is interesseert me in dit geval niet.

Hiervoor heb ik allerlei tutorials uit zitten pluizen, dingen geprobeerd, maar op de een of andere manier krijg ik maar geen goede match. Of hij vindt veel te veel matches, of helemaal niets. De string die ik wil matchen is:

beginnend met "[b:"
gevolgd door dat $uid wat me niet uitmaakt
eindigend met "]"
Daarna volgt de tekst die dikgedrukt moet zijn, dus ik dacht aan iets als ".*?" voor in de regex.
daarna komt "[/b]"

Het bovenstaande stukje moet vervangen worden door:

"<b>De tekst die dikgedrukt moet zijn</b>"

Hopelijk kunnen jullie me hierbij helpen, of in ieder geval de goede richting in duwen. Links naar tutorials over regex zijn natuurlijk welkom, maar ik heb er al redelijk wat gehad, ook via google.

Een vergissing is menselijk, maar om er echt een puinhoop van te maken heb je een computer nodig.


Acties:
  • 0 Henk 'm!

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 06-09 00:37

curry684

left part of the evil twins

Professionele website nodig?


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 23:12
Met een ereg issie ongeveer zo:
PHP:
1
2
3
eregi_replace("\\\[b:[^\\\[]*\\]([^\\\[]*)\\\[/b\\]","<b>\\1</b>",$string);
//afgeleid van:
//eregi_replace("\\\[afk=([^\\\[]*)\\]([^\\\[]*)\\\[/afk\\]","<abbr title=\"\\1\">\\2</abbr>",$string);


Verder ben ik geen held in regexen enzo, maar ik snap er geen biet van wat een $uid in zo'n UBB tag zou moeten doen. Je user weet toch niet welk id hij in moet typen? Hoe kan hij dan text bold maken :?

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Superdeboer
  • Registratie: December 2002
  • Niet online

Superdeboer

Sa-weee-tah

T-MOB schreef op maandag 28 maart 2005 @ 01:11:
Verder ben ik geen held in regexen enzo, maar ik snap er geen biet van wat een $uid in zo'n UBB tag zou moeten doen. Je user weet toch niet welk id hij in moet typen? Hoe kan hij dan text bold maken :?
Als ik het goed begrijp, heeft TS een phpBB-database...
De BB-code parser van phpBB voegt aan iedere tag een at random (tijdens het parsen) gegenereerde $uid toe, om op die manier goed te kunnen nesten. Dat staat min of meer hier uitgelegd.

Zoals ik de topicstarter begrijp, gaat hij dus uit van data uit een phpBB-database... en wil hij die nu door een zélfgeschreven BB-code parser heentrekken; dat snap ik niet. Waarom kan die data niet gewoon door de phpBB-parser zélf geparsed worden? Zeker gezien het feit dat je wel naar de code uit die parser zit te kijken zo te zien... :)

When I write my code, only God and I know what it means. One week later, only God knows.
Hell yes it's a Cuban Cigar, but I'm not supporting their economy, I'm burning their fields.


Acties:
  • 0 Henk 'm!

  • GambitRS
  • Registratie: Juni 2001
  • Laatst online: 13-06-2013

GambitRS

w00t

T-MOB schreef op maandag 28 maart 2005 @ 01:11:
Verder ben ik geen held in regexen enzo, maar ik snap er geen biet van wat een $uid in zo'n UBB tag zou moeten doen. Je user weet toch niet welk id hij in moet typen? Hoe kan hij dan text bold maken :?
Ik denk dat je zo kan zien welke user de tag heeft gezet (er vanuitgaande dat de code die UID er zelf bij zet). Dan neem ik aan dat sommige users bijvoorbeeld alleen dingen bold mogen maken terwijl andere users (admins ofzo) ook kleurtjes mogen gebruiken. Daar zou ik het voor gebruiken iig :+

MechWarrior || Monsters Game


Acties:
  • 0 Henk 'm!

  • Kaastosti
  • Registratie: Juni 2000
  • Laatst online: 22-09 17:13

Kaastosti

Vrolijkheid alom!

Topicstarter
Ik wil die code uit de database halen en laten zien buiten het forum zelf. Daar buiten heeft een gebruiker geen uid. Daarnaast kunnen verschillende gebruikers het bron-bericht invoeren, waardoor ook dat nummertje veranderd. Dat als constante beschouwen gaat dus niet.

Aangezien ik buiten het forum geen uid heb, kan ik daar ook niets mee doen. De parser van phpBB zelf gebruiken zal dus naar mijn idee niet gaan werken.

Een vergissing is menselijk, maar om er echt een puinhoop van te maken heb je een computer nodig.


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 23:12
Superdeboer schreef op maandag 28 maart 2005 @ 01:19:
[...]

Als ik het goed begrijp, heeft TS een phpBB-database...
De BB-code parser van phpBB voegt aan iedere tag een at random (tijdens het parsen) gegenereerde $uid toe, om op die manier goed te kunnen nesten. Dat staat min of meer hier uitgelegd.

Zoals ik de topicstarter begrijp, gaat hij dus uit van data uit een phpBB-database... en wil hij die nu door een zélfgeschreven BB-code parser heentrekken; dat snap ik niet. Waarom kan die data niet gewoon door de phpBB-parser zélf geparsed worden? Zeker gezien het feit dat je wel naar de code uit die parser zit te kijken zo te zien... :)
Aha, maar wat ik uit jouw link op kan maken is dat de phpBB parser de "$uid" ook toevoegt aan de sluitmessage. Eigenlijk best een clever systeem om te zorgen dat je op weergavetijd alleen maar simpele str_replace()'s hoeft uit te voeren ipv een hele operatie om te bepalen welke sluit-tag bij welke openingstag hoort. Daarmee sluit ik me bij je aan wat betreft de vraag waarom TS deze code's door een eigen parser wil halen...

edit:
Kaastosti schreef op maandag 28 maart 2005 @ 01:28:
Ik wil die code uit de database halen en laten zien buiten het forum zelf. Daar buiten heeft een gebruiker geen uid. Daarnaast kunnen verschillende gebruikers het bron-bericht invoeren, waardoor ook dat nummertje veranderd. Dat als constante beschouwen gaat dus niet.

Aangezien ik buiten het forum geen uid heb, kan ik daar ook niets mee doen. De parser van phpBB zelf gebruiken zal dus naar mijn idee niet gaan werken.
Voor zover ik kon opmaken via de link van Superdeboer heeft $uid niks met de ingelogde gebruiker te maken. Volgens mij zou je de parser van PHPbb dus gewoon moeten kunnen gebruiken (al geprobeerd ?). Anyway, hier de uitleg die ik kon vinden:
bron
Here's v2.0 bbcode in a nutshell:

The problem is that parsing the nestable tags (code, quote, and list) is necessarily slow. There's no way around that, other than not actually bothering to find matching pairs of tags. But if we don;t find matching pairs of tags, users can thrash the layout of an entire page just by hanving an unmatched opening tag in their message.

So, what I did was break down that task into 2 separate steps:
1) Recognizing the tags.
2) Actually replacing the tags with HTML code.

Step 1 is done before we put the post in the database, and step 2 is done at pageview time.

What step 1 does is to replace a matching tag pair with a pair of the same tags, but with the addition of a UID string. Example:
[...]
becomes [quote:UID] ..... [/quote:UID]. The UID part is currently a 10-character random alphanumeric string. Its length can be tweaked for performance, and I haven't decided what the final value will be yet.

So, the second pass can just blindly run a bunch of str_replace() calls, looking for "[quote:UID]" to replace with the starting quote HTML, and "[/quote:UID]" to replace with the ending quote HTML. This process is quite fast.

Also, the first pass can be very easily reversed for the editpost page - we just run str_replace() and basically strip the UIDs from the tags.

So, now the HTML that's used to generate BBCode is no longer stored in the database. This means that HTML can be changed, or specific tags disabled, at any time by the admin without breaking the reversal process, and with the effects taking place immediately across the whole board, including existing posts.


No, it's not possible to match the nested tags with a regular expression, that's the whole heart of the problem. I'll try and explain why:

Essentially, we want to match something like this, right:
#[tag](.*)[/tag]#

Now, there are two ways the quantifier in the middle there can match - either greedy or non-greedy. Look at the following example code block, where I;ll indicate the tags each method will match:
[tag] -- greedy start, non-greedy start
[tag]

[/tag] -- non-greedy end
[/tag] -- greedy end

So, in this case, the non-greedy match fails - it doesn't do the right thing at all. But, the greedy match works fine. Repeated applications of that regexp will do the job.

So, consider our next example. I'll do the same thing as before:
[tag] -- greedy start, non-greedy start

[/tag] -- non-greedy end
[tag]

[/tag] -- greedy end

In this case, the exact opposite is true. The greedy tag fails completely, and the non-greedy tag does the right thing. So, since these two cases could easily occur inside the same message, we can see that there's no way to accomplish this with a regular expression.

[ Voor 61% gewijzigd door T-MOB op 28-03-2005 01:37 ]

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Kaastosti
  • Registratie: Juni 2000
  • Laatst online: 22-09 17:13

Kaastosti

Vrolijkheid alom!

Topicstarter
Oh wacht ik ging er van uit dat die uid een 'user id' was... terwijl het een indicator is voor welke sluittag bij welke openingstag hoor. Best een ingenieus systeem idd :)

Mijn fout was in ieder geval het vergissen in de betekenis van de uid... misschien inderdaad toch maar gewoon die parser van phpBB gebruiken. met de 'nieuwe' betekenis moet het goedkomen. Bedankt voor de aanwijzingen... damn dit had ik zelf kunnen vinden :|

Update
Het gebruik van de uid bleek toch lastiger dan gedacht, aangezien deze wordt opgezocht in een lap code die niet in een functie zit. Dat is dus lastig aan te roepen vanuit een eigen stukje code. Met de wetenschap dat het geen user id is maar een willekeurige code ben ik terug gaan zoeken naar een oplossing met een regex... en wonder boven wonder helemaal zelf gevonden ook :)

PHP:
1
$source = preg_replace("#\\[[b]:(.*)](.*)\\[/b:\\1]#","<b>\\2</b>",$source)

[ Voor 107% gewijzigd door Kaastosti op 28-03-2005 12:33 ]

Een vergissing is menselijk, maar om er echt een puinhoop van te maken heb je een computer nodig.


Acties:
  • 0 Henk 'm!

  • Domokoen
  • Registratie: Januari 2003
  • Laatst online: 21-09 21:50
In plaats van je eigen parser te maken, kan je natuurlijk ook even bij PEAR kijken: http://pear.php.net , die hebben een kant en klaar iets voor wat je aan het maken bent. Maar 't is natuurlijk ook leuk om het zelf te doen. :)
Pagina: 1