[PHP][PCRE] Vervang alles behalve tussen x en y

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • TygeR
  • Registratie: Oktober 2000
  • Laatst online: 06-02 16:23
Hallo,

Ik probeer een PCRE regular expression te maken die alle instances van iets vervangt door iets anders behalve wanneer het iets tussen x en y staat. Bijvoorbeeld x = |code| en y=|/code| vervolgens wil ik < vervangen door < maar niet als de < tussen de tags code in ligt.

om iets <b>bold</b> te maken moet je |code|<b>bold</b>|/code|

moet na replace dus:

om iets <b>bold</b> te maken moet je |code|<b>bold</b>|/code|

worden, is dit mogelijk in een enkele regexp? en zo ja kan ik ook meerdere x en y vars meenemen dus bijvoorbeeld niet als het tussen |code| en |/code| of tussen |html| en |/html| staat?

Acties:
  • 0 Henk 'm!

  • IntToStr
  • Registratie: December 2003
  • Laatst online: 20:57
Ik heb 2x geprobeerd dit te lezen, maar ik kan alleen maar gokken wat je bedoelt... Misschien iets duidelijker uitleggen en heb je zelf al een poging gedaan?

Acties:
  • 0 Henk 'm!

  • flashin
  • Registratie: Augustus 2002
  • Laatst online: 17-12-2023
mij is het opzich wel duidelijk, alleen wat is je reden om dit in 1 regex te doen?

Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

Regular expressions zijn niet bedoeld voor dit soort dingen. Contextgevoeligheid kun je veel beter voor elkaar krijgen met een 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!

  • _js_
  • Registratie: Oktober 2002
  • Laatst online: 18-08 21:31
Het kan denk ik wel, maar het is een stuk moeilijker dan dat het zou zijn wanneer je gewoon token voor token de tekst door gaat met een stack-based parser.

Acties:
  • 0 Henk 'm!

  • TygeR
  • Registratie: Oktober 2000
  • Laatst online: 06-02 16:23
Ik zal het nog een keer proberen wat duidelijker te maken, ik wil in php doormiddel van een preg_replace in een stuk text bijvoorbeeld de < en de > vervangen door < en > maar niet wanneer dit tussen bijvoorbeeld |code| en |/code| of |html| en |/html| staat. want als het daartussen staat wil ik dat het gewoon < en > blijft.

voor de replace gebruik ik

$regexp[] = "/\</";
$replace[] = '<';
$text = preg_replace($regexp,$replace,$text);

Ik kan alleen niet vinden hoe ik hier uitzonderingen op kan toepassen dus bijvoorbeeld niet wanneer dit matched:
"/\|code\|.*?\<.*?\|\/code\|/"

Acties:
  • 0 Henk 'm!

  • Patriot
  • Registratie: December 2004
  • Laatst online: 16-09 13:49

Patriot

Fulltime #whatpulsert

Het verhaal is wat onduidelijk omdat GoT de entities niet encode (dus &lt; wordt <)

[ontopic]

Wat je wilt is waarschijnlijk via veel omwegen wel mogelijk met een enkele regex, en misschien iets 'makkelijker' met meerdere regexes. Echter, het parsen van dit soort SGML-achtige structuren is niet iets wat je wilt doen met regular expressions. Regexes voldoen misschien voor de simpelere tags, maar bij de wat ingewikkeldere constructies loop je al snel tegen problemen aan omdat je onzettend ingewikkelde regexes in elkaar gaat bouwen.

Wat je wél kunt gebruiken om ook dit soort dingen te ondersteunen, is het bouwen (of makkelijker, van iemand anders lenen) van een stack-based parser. Google is daarin je vriend, maar ook zeker even de GoT-search gebruiken want het onderwerp komt hier wel vaker langs.

Acties:
  • 0 Henk 'm!

  • TygeR
  • Registratie: Oktober 2000
  • Laatst online: 06-02 16:23
Ik ben een parser aan het omschrijven naar een single pass regexp, hiermee ben ik nagenoeg klaar alleen hetgeen ik nu vraagt lukt nog niet. Voordeel voor mij is dat ik de parser (regexp) zowel in javascript als in PHP kan gebuiken.

Acties:
  • 0 Henk 'm!

  • IntToStr
  • Registratie: December 2003
  • Laatst online: 20:57
Als het puur gaat om bbcode te parsen, wat ik verwacht hier, is een stackbased parser uiteraard een stuk handiger. Sterkte met meervoudig geneste tags in regular expressions ;-)

Je krijgt een mooie tree en je kunt nog aangeven op welke plaats het foutging ook in geval van niet te parsen data.

Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

TygeR schreef op maandag 17 augustus 2009 @ 16:07:
Ik ben een parser aan het omschrijven naar een single pass regexp, hiermee ben ik nagenoeg klaar alleen hetgeen ik nu vraagt lukt nog niet. Voordeel voor mij is dat ik de parser (regexp) zowel in javascript als in PHP kan gebuiken.
Dat lukt je met een stackbased parser ook wel. ;) Zoals ik al zei: regular expressions zijn hier absoluut niet geschikt voor en je moet ze voor dit soort dingen ook niet willen gebruiken.

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

  • TygeR
  • Registratie: Oktober 2000
  • Laatst online: 06-02 16:23
Momenteel vindt ik het erg lastig dat ik elke keer alle wijzigingen zowel in javascript als in php moet doorvoeren om het geheel compatible te houden. dit hoef ik met regexp niet... met een stack based parser blijf ik hiermee bezig, of ik zou een parser moeten schrijven die javascript in php omzet of andersom, lijkt me nog omslachtiger? het gaan nu nog maar om een paar uitzonderingen zoals boven omschreven en de parser werkt singlepass in regexp, en sneller dan dat hij werkte als stack based parser.

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Ik zie even het nut van de JS versie niet, en als die wel nodig/vereist is kun je natuurlijk ook met AJAX even de 'code' naar de PHP versie stampen; hoef je geen JS versie te onderhouden :Y)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • _Gekkie_
  • Registratie: Oktober 2000
  • Laatst online: 24-06 20:21

_Gekkie_

And the cow said: Helloooooow?

Begrijp ik de voorbeelden goed en probeer je BB-tags (of een andere vorm) te fixen? Daar zijn gewoon standaard libraries voor die dit voor je regelen... (zowel server als clientside) Ik zou daar eerst naar kijken voordat je zelf een oplossing in elkaar draait...

Gekkie is a proud member of TheBenny!


Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

TygeR schreef op maandag 17 augustus 2009 @ 16:13:
Momenteel vindt ik het erg lastig dat ik elke keer alle wijzigingen zowel in javascript als in php moet doorvoeren om het geheel compatible te houden. dit hoef ik met regexp niet... met een stack based parser blijf ik hiermee bezig, of ik zou een parser moeten schrijven die javascript in php omzet of andersom, lijkt me nog omslachtiger? het gaan nu nog maar om een paar uitzonderingen zoals boven omschreven en de parser werkt singlepass in regexp, en sneller dan dat hij werkte als stack based parser.
Dan zul je moeten kiezen, ofwel je ondersteunt dit wel en je doet het goed (stackbased parser!), ofwel je blijft met regular expressions werken en legt je erbij neer dat dit niet zomaar kan zonder een compleet onleesbare en niet onderhoudbare regular expression.

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

  • TygeR
  • Registratie: Oktober 2000
  • Laatst online: 06-02 16:23
Waarom hamert iedereen nou zo op een stack based parser? die is ruim 10x trager dan de huidige oplossing ook met geneste structuren simpel voorbeeld:
code:
1
[b][i][u]text[/u][/i][/b]


in regexp is dit:
PHP:
1
2
3
4
5
6
        $simpleTags = array("b","i","u","s","h1","h2","h3","h4","h5","h6","sup","sub","small");
        foreach($simpleTags as $tag)
        {
            $regexp[] = "/\[$tag](.*?)\[\/$tag]/";
            $replace[] = "<$tag>".'$1'."</$tag>";
        }


Wat een stuk sneller en simpeler is dan met een stack based parser.

In mijn huidige code (regexp) parse ik een volledige pagina aan BBcode binnen 0.0004sec de stackbased parser doet 0.00426sec over de zelfde pagina.

Ik heb alleen problemen met de code tag en de html tag die ik graag wil toevoegen, en wil graag weten of ik een regexp kan maken voor een replace die tags tussen 2 code tags of 2 html tags negeert.
Nu blijkt het wel te kunnen zeggen jullie, alleen is er niemand die mij wil aangeven hoe. Ik kan dit op internet nergens vinden... Overigens nesten de html en de code tags niet omdat alles wat daarbinnen valt niet hoeft te worden geparsed tot de closing tag.

[ Voor 17% gewijzigd door TygeR op 17-08-2009 22:10 ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

TygeR schreef op maandag 17 augustus 2009 @ 21:52:
Waarom hamert iedereen nou zo op een stack based parser? die is ruim 10x trager dan de huidige oplossing ook met geneste structuren bijvoorbeeld
code:
1
[b][i][u]text[/b][/i][/u]
En wat voor output levert dat op?
En hoe ga je om met nesting van dezelfde tags? Dus bijvoorbeeld:
code:
1
2
3
[quote]blabala
    [quote]tralala[/quote]
[/quote]
In mijn huidige code (regexp) parse ik een volledige pagina aan BBcode binnen 0.0004sec de stackbased parser doet 0.00426sec over de zelfde pagina.
En waarom is dat belangrijk? 4 milliseconden is alsnog niets, zeker als je de geparsede versie ook gewoon opslaat naast de 'raw' versie. Als je alles 'on-the-fly' gaat parsen dan zou ik eerder daar iets aan doen.

Verder zeggen die getallen nog niets; ik weet niet hoe efficient jouw stack-based parser is, maar ik denk wel dat hij in ieder geval beter schaalt naarmate je meer verschillende tags wilt ondersteunen dan een regexp-based parser en flexibeler is (denk aan support voor short-closing tags, attributen bij tags, error-correctie bij tag-mismatches etcetera).
Ik heb alleen problemen met de code tag en de html tag die ik graag wil toevoegen, en wil graag weten of ik een regexp kan maken voor een replace die tags tussen 2 code tags of 2 html tags negeert.
Nu blijkt het wel te kunnen zeggen jullie, alleen is er niemand die mij wil aangeven hoe. Ik kan dit op internet nergens vinden... Overigens nesten de html en de code tags niet omdat alles wat daarbinnen valt niet hoeft te worden geparsed tot de closing tag.
Ik denk dat je al snel moet terugvallen op callback-functies voor je expressies en misschien zelfs delen moet 'pre-matchen' om later weer te kunnen corrigeren. Been there, done that, will never do it again*...

* de laatste keer had ik een expressie die bij een tag-mismatch dusdanig ging backtracken dat PHP crashde met een segfault. Vervolgens meteen herschreven naar een mini-stackbased parsertje die ook nog eens 10x sneller bleek :)

[ Voor 5% gewijzigd door crisp op 17-08-2009 22:14 ]

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Als je het per se zo wil: Voor zowel html als code, zoek de begin tag, zoek de eindtag, en gooi htmlspecialchars() over wat daartussen zit. En daarna doe je je trucs voor de rest van de tags en klaar ben je. :)
...
tenminste tot het volgende probleem, en dan wordt het steeds ingewikkelder cq onmogelijk qua volgorde. ;)

{signature}


Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

TygeR schreef op maandag 17 augustus 2009 @ 21:52:
Waarom hamert iedereen nou zo op een stack based parser?
Je kan ook gewoon het antwoord niet willen begrijpen...

Wat jij wil kan niet. Niet in één regexp, zeker niet een leesbare. Een stackbased parser doet dat beter en afhankelijk van de situatie zelfs sneller. En bovendien kun je zo'n parser zelfs tot in zeker mate foutjes laten verbeteren.

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

  • TygeR
  • Registratie: Oktober 2000
  • Laatst online: 06-02 16:23
crisp schreef op maandag 17 augustus 2009 @ 22:10:
[...]

En wat voor output levert dat op?
En hoe ga je om met nesting van dezelfde tags? Dus bijvoorbeeld:
code:
1
2
3
[quote]blabala
    [quote]tralala[/quote]
[/quote]


En waarom is dat belangrijk? 4 milliseconden is alsnog niets, zeker als je de geparsede versie ook gewoon opslaat naast de 'raw' versie. Als je alles 'on-the-fly' gaat parsen dan zou ik eerder daar iets aan doen.

[...]
Bij verkeerd geneste structuren wordt de laatste code genegeerd. een quote in een quote plaatsen is met mijn parser niet mogelijk.

Die 4 miliseconden is van belang omdat de pagina met elke invoer van de gebruiker live geupdate wordt. Live preview, vandaar ook dat ik graag een stuk code heb dat zowel in javascript als in php gebruikt kan worden.
Elke onkeypress via AJAX een vertaling opvragen lijkt mij niet heel erg voor de hand liggend.

Maarja als het echt niet anders kan zal ik voor die paar uitzonderingen wel een stack based mini-parsertje maken die bepaalde delen vervangt door een anchor en opslaat in een array waarnaa naa de bewerking van de regexp die delen weer teruggeplaatst kunnen worden.

Acties:
  • 0 Henk 'm!

Verwijderd

Nee, nee, nee. Je moet niets "vervangen" in de originele input. Je parset gewoon een bepaalde input en genereert aan de hand van wat je tegenkomt nieuwe output. Door een stack bij te houden weet je de context en kun je beslissen wat te doen. Zo kun je bepalen dat binnen [quote] en [/quote] wel iets als [b] voor mag komen, maar niet [quote] of [image]. Of misschien wil je dat pas vanaf 3 niveau's diep.

In vrijwel alle gevallen is een simpele stack based parser zo geschreven,

Acties:
  • 0 Henk 'm!

  • TygeR
  • Registratie: Oktober 2000
  • Laatst online: 06-02 16:23
Verwijderd schreef op dinsdag 18 augustus 2009 @ 08:19:
[...]

Nee, nee, nee. Je moet niets "vervangen" in de originele input. Je parset gewoon een bepaalde input en genereert aan de hand van wat je tegenkomt nieuwe output. Door een stack bij te houden weet je de context en kun je beslissen wat te doen. Zo kun je bepalen dat binnen [quote] en [/quote] wel iets als [b] voor mag komen, maar niet \[quote] of [image]. Of misschien wil je dat pas vanaf 3 niveau's diep.

In vrijwel alle gevallen is een simpele stack based parser zo geschreven,
Ik zal mij daar eens wat verder in verdiepen, momenteel heb ik dus wel een simpel stack based parser voor het geheel maar die is in javascript en dat is al helemaal geen gunstige locatie in verband met sommige bewerkingen omdat ik dan altijd de client nodig heb. Bijvoorbeeld bij het versturen van digest mails en dergelijke is dit knap lastig ;-). Misschien dat ik als het echt niet anders kan de live preview alleen ga verversen op request (knopje verversen). En dat ik dan een uitgebreide parser in php zet... Het herstellen van fouten is inderdaad een mooie functie die een parser wel kan en wat in regexp niet echt gaat lukken. Momenteel laat de regexp dan de foutieve code zoals niet afgesloten tags, of onvolledige tabellen en dergelijke gewoon ongewijzigd staan.

Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

Ik zou je ook willen afraden om zowel een stackbased parser als regexps te gaan gebruiken. Je gaat met die parser toch al door de tekst heen voor dit ene ding, waarom zou je in diezelfde pass niet alles doen? :)

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

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Misschien dat het ook nuttig is om wat achtergrond uit te leggen. De naam "regex" komt van "regular expressions". Dat zijn expressies die een "regular language" beschrijven. Een regular language heeft als kenmerk dat de hoeveelheid geheugen die je nodig hebt om een document te parsen niet afhangt van je document, maar alleen van de exacte syntaxregels van je taal.

Een tag-based markup language heeft juist als eigenschap dat je bij moet houden hoeveel open tags je gezien hebt. Dat is potentieel oneindig. Het geheugengebruik wordt dus beinvloed door je documentgrootte.

Om die reden weten wij dus zo zeker dat reguliere expressies niet de juiste keuze zijn om jouw tag-taal te parsen. Dat is geen mening, dat is wiskunde.

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

Pagina: 1