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

[PHP] preg_replace Alle < tussen <pre> en </pre>

Pagina: 1
Acties:

Onderwerpen


  • -DarkShadow-
  • Registratie: December 2001
  • Niet online
Ik wil met preg_replace alle < en > karakters tussen de <pre> en </pre> tags vervangen door de respectievelijke HTML karakters. Nu heb ik mezelf al door enkele tutorials geworsteld, maar ik kom er niet uit.

Voorbeeld:
code:
1
topic. <pre><?php echo 'GoT is top!';?><?php echo phpinfo(); ?></pre> en zo verder

Wil ik veranderen in:
code:
1
topic. <pre>&lt;?php echo 'GoT is top!';?&gt;&lt;?php echo phpinfo(); ?&gt;</pre> en zo verder


Ik heb dit in elkaar geknutseld, maar dit werkt met slechts één < in je <pre> blok:
code:
1
$text = preg_replace('/<pre>(.*)<(.*)<\/pre>/', '<pre>$1&lt;$2</pre>', $text);

Specialist in:
Soldeerstations
Oscilloscoop


  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
Preg match hoor je niet voor html te gebruiken. Dan krijg je problemen met nested elements etc.

Als dat niet uit maakt, gebruik dan preg_match_all. En replace $match[0] met '<pre>' . htmlentities($match[1]) .'</pre>' op deze regexp: /<pre>(.*)<\/pre>/

  • Dr. Horrible
  • Registratie: April 2007
  • Laatst online: 15:24
http://www.php.net/manual/en/function.htmlspecialchars.php

Volgens mij is het veel makkelijker te doen met deze functie.

  • -DarkShadow-
  • Registratie: December 2001
  • Niet online
Het gaat om de weergave van code in blog posts. De code wordt door de gebruiker in een pre blok gezet. Wanneer de code wordt weergegeven, word er een JS syntax highlighter gebruikt om de code mooi te maken.
Er staat ook HTML code in de string die heel moet blijven.

[ Voor 42% gewijzigd door -DarkShadow- op 02-04-2011 12:23 ]

Specialist in:
Soldeerstations
Oscilloscoop


Verwijderd

Je wil niet dat tussenliggende </pre>'s worden opgepakt en dit gebeurt bij alle bovenstaande regexes, want in PHP zijn ?, * en + greedy. Voorbeeldje:
code:
1
Lorem <pre>ipsum <?dolor</pre> sit amet, <pre>consectetur</pre> adipisicing elit,
wordt
code:
1
Lorem <pre>ipsum &lt;?dolor&lt;/pre&gt; sit amet, &lt;pre&gt;consectetur</pre> adipisicing elit,
(als je ook > zou vervangen).

Wat je zou kunnen gebruiken is dit:
code:
1
/<pre>(([^<]*)<(?!\/pre>))*([^<]*)<\/pre>/
Voer dit aan preg_match_all, kijk wat er gebeurt en leer ervan :) De clou hier is het gebruik van lookahead assertions.


-edit- Argh, het originele probleem blijft bestaan. Ik kijk even verder.

[ Voor 5% gewijzigd door Verwijderd op 02-04-2011 13:09 . Reden: LLorem? Llama! ]


  • -DarkShadow-
  • Registratie: December 2001
  • Niet online
Deze zorgt ook voor problemen:
code:
1
<pre>test<<test</pre>


En ik ben vergeten te melden dat <pre class="..."> ook ondersteund moet worden. Waarvoor /<pre[^>]*>/ gebruikt kan worden.

We komen steeds dichter bij :)

[ Voor 20% gewijzigd door -DarkShadow- op 02-04-2011 12:47 ]

Specialist in:
Soldeerstations
Oscilloscoop


Verwijderd

Attributen zijn op zich triviaal, het probleem is hier dat je herhaalde subgroepen wil vervangen. Misschien moet je toch preg_replace_callback gaan gebruiken. Je moet dan denken aan iets als
code:
1
2
3
4
5
function jeCallback($matches) {
    return '<pre>' . preg_replace('/</', '&lt;', preg_replace('/>/', '&gt;', $matches[1])) . '</pre>';
}

preg_replace_callback("/<pre>((?:[^<]*<(?!\/pre>))*[^<]*)<\/pre>/", 'jeCallback', $jeTekst);
(mijn PHP is nogal roestig, dus let op ;))

[ Voor 40% gewijzigd door Verwijderd op 02-04-2011 13:09 ]


  • FragFrog
  • Registratie: September 2001
  • Laatst online: 11:39
ReenL schreef op zaterdag 02 april 2011 @ 12:01:
Preg match hoor je niet voor html te gebruiken. Dan krijg je problemen met nested elements etc.
Hier sluit ik me bij aan: als je HTML enigszins parsebaar is kun je een DOMDocument gebruiken om deze netjes te parsen. Vervolgens is het erg simpel om met getElementsByTagName alle <pre> tag's en hun content eruit te halen :)

[ Site ] [ twitch ] [ jijbuis ]


  • Wiethoofd
  • Registratie: Juli 2007
  • Laatst online: 17-11 00:47

Wiethoofd

Broadcast TOM

Is het niet makkelijker/handiger/eenvoudiger om de code door een user tussen [pre] tags te laten zetten en dan vervolgens alles daartussen te vervangen wat vervangen moet worden?

En wat versta je onder 'er staat ook html code in die string die heel moet blijven'?

Volg me op Twitter/X & Bluesky


  • -DarkShadow-
  • Registratie: December 2001
  • Niet online
Wiethoofd schreef op zaterdag 02 april 2011 @ 14:29:
En wat versta je onder 'er staat ook html code in die string die heel moet blijven'?
De gebruiker submit een blogpost (de string) waarin naast <pre> ook andere tags worden gebruikt. Tags buiten pre-blokken moeten gewoon geparsed worden door de browser.

Specialist in:
Soldeerstations
Oscilloscoop


  • Matis
  • Registratie: Januari 2007
  • Laatst online: 26-11 20:59

Matis

Rubber Rocket

Ik ben een ramp als het gaat over regexpen, dus daarom zal ik jouw specifieke probleem anders oplossen.
Wat ik zou doen is het volgende:
Laadt de html(pagina) als DOM-object middels: http://www.php.net/manual/en/domdocument.loadhtmlfile.php
Schrijf daarna een XPath welke jouw pre-waardes teruggeeft middels: http://www.php.net/manual/en/domxpath.query.php
Vervang voor elke match de < en > door hun bijbehorende html-waarde en maak daar een tijdelijke DOMNode voor aan.
Vervang de gematchte DOMNode door de zojuist gegenereerde DOMNode middels: http://www.php.net/manual/en/domnode.replacechild.php
Je kunt daarna eventueel de DOM opslaan of doorgeven aan de browser.

If money talks then I'm a mime
If time is money then I'm out of time


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

drm

f0pc0dert

Het kan opzich prima met regular expressions, maar misschien is het wel eens goed om te kijken naar een andere vorm van markup, zoals reStucturedText (PHP implementatie) of Markdown (PHP implementatie), waarbij je het hele proces van posts schrijven en opmaken ueberhaupt veel makkelijker maakt. Mijn ervaring op mijn eigen blog is dat het heel irritant is om met een wysiwyg-editor posts te schrijven omdat je dan uiteindelijk vaak meer tijd kwijt bent aan opmaak dan aan content.

Als je toch bij wysiwyg wilt blijven, dan zou je ook eens naar de (source code van) GeSHi plugin voor wordpress kunnen kijken, die doet ongeveer wat jij wilt.

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


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

NMe

Quia Ego Sic Dico.

Wiethoofd schreef op zaterdag 02 april 2011 @ 14:29:
Is het niet makkelijker/handiger/eenvoudiger om de code door een user tussen [pre] tags te laten zetten en dan vervolgens alles daartussen te vervangen wat vervangen moet worden?
Ja, want spul tussen [pre] en [/pre] vervangen is substantieel makkelijker dan spul tussen <pre> en </pre> vervangen....

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


  • Wiethoofd
  • Registratie: Juli 2007
  • Laatst online: 17-11 00:47

Wiethoofd

Broadcast TOM

NMe schreef op zondag 03 april 2011 @ 15:19:
Ja, want spul tussen [pre] en [/pre] vervangen is substantieel makkelijker dan spul tussen <pre> en </pre> vervangen....
Het is veel makkelijker te matchen als je <pre>'s in je eigen <pre> neer wilt kunnen zetten...

Volg me op Twitter/X & Bluesky


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

NMe

Quia Ego Sic Dico.

Wiethoofd schreef op zondag 03 april 2011 @ 15:21:
[...]

Het is veel makkelijker te matchen als je <pre>'s in je eigen <pre> neer wilt kunnen zetten...
Ja, en veel moeilijker als je een keer [pre]'s in je eigen [pre] wil zetten. Of je nou <pre>, [pre] of voor mijn part ^pre^ of #pre# gebruikt maakt geen ene moer uit voor hoe makkelijk je regexp wordt, tenzij je in gaat boeten op dit vlak.

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


  • -DarkShadow-
  • Registratie: December 2001
  • Niet online
Bedankt voor alle antwoorden :) Uiteindelijk heb ik een Markdown filter gebruikt wat al in het framework zit gebakken.

Specialist in:
Soldeerstations
Oscilloscoop


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

drm

f0pc0dert

d:)b

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


Verwijderd

Verwijderd schreef op zaterdag 02 april 2011 @ 12:28:
Je wil niet dat tussenliggende </pre>'s worden opgepakt en dit gebeurt bij alle bovenstaande regexes, want in PHP zijn ?, * en + greedy. Voorbeeldje:
code:
1
Lorem <pre>ipsum <?dolor</pre> sit amet, <pre>consectetur</pre> adipisicing elit,
wordt
code:
1
Lorem <pre>ipsum &lt;?dolor&lt;/pre&gt; sit amet, &lt;pre&gt;consectetur</pre> adipisicing elit,
(als je ook > zou vervangen).

Wat je zou kunnen gebruiken is dit:
code:
1
/<pre>(([^<]*)<(?!\/pre>))*([^<]*)<\/pre>/
Voer dit aan preg_match_all, kijk wat er gebeurt en leer ervan :) De clou hier is het gebruik van lookahead assertions.


-edit- Argh, het originele probleem blijft bestaan. Ik kijk even verder.
Inmiddels irrelevant, maar misschien wel nuttig: in PHP kun je ook vlaggetjes aan je regex toevoegen om het lazy te maken. Net zoals je vlaggetjes hebt voor case insensitive etc. zoiets:

// edit: let op de /U dus in de regex :P
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

$string = 'Lorem <pre class="class">ipsum <b>dolor</b></pre> sit amet, <pre>consectetur</pre> adipisicing elit';

preg_match_all('/<pre[^>]*>(.*)<\/pre>/U', $string, $matches, PREG_SET_ORDER); 

foreach($matches as $match) {
    $string = str_replace($match[1], str_replace('>', '&gt;', str_replace('<', '&lt;', $match[1])), $string);
}

echo $string; //Lorem <pre class="class">ipsum &lt;b&gt;dolor&lt;/b&gt;</pre> sit amet, <pre>consectetur</pre> adipisicing elit

?>


heb het verder niet getest op verdere uitzonderingen...

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

NMe

Quia Ego Sic Dico.

Met .*? ben je sowieso ungreedy. :)

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


Verwijderd

NMe schreef op woensdag 06 april 2011 @ 11:47:
Met .*? ben je sowieso ungreedy. :)
Ik kan het mis hebben, maar volgens mij ligt het subtieler. Je wil alle karakters oppakken tot een <, behalve als het een < gevolgd door /pre> betreft. Als je dat precies één keer per pre-blok wil doen gaat het misschien nog goed, maar in andere gevallen denk ik dat het ambigu wordt.

[ Voor 3% gewijzigd door Verwijderd op 06-04-2011 12:06 ]


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

NMe

Quia Ego Sic Dico.

Nee hoor. Met #<pre[^>]*>(.*?)</pre>#i (ik gebruik even een andere dilimiter ;)) pak je alles vanaf een begin-<pre> tot en met de eerstvolgende </pre>. Non-greedy. :)

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


Verwijderd

NMe schreef op woensdag 06 april 2011 @ 12:10:
Nee hoor. Met #<pre[^>]*>(.*?)</pre>#i (ik gebruik even een andere dilimiter ;)) pak je alles vanaf een begin-<pre> tot en met de eerstvolgende </pre>. Non-greedy. :)
Yup, zelfde resultaat :)

Verwijderd

Ik denk duidelijk te moeilijk. :')

  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 26-11 20:53

Ventieldopje

I'm not your pal, mate!

PHP:
1
2
3
4
5
6
7
8
9
10
11
<?php

$raw = "<pre><?php echo 'GoT is top!';?><?php echo phpinfo(); ?></pre>";

// -11 is lengte van <pre> </pre>
$rawpre = substr($raw, strpos($raw, "<pre>"), strrpos($raw, "</pre>") - 11);

$output = str_replace("<", "&lt;", $rawpre);
$output = str_replace(">", "&gt;", $output);

?>


Zo even uit mn hoofd hoor, denk dat dit ongeveer is wat je zoekt ;)

Met deze methode is het zelfs mogelijk om <pre>en </pre> binnen <pre> en </pre> te gebruiken :+

[ Voor 11% gewijzigd door Ventieldopje op 06-04-2011 13:02 ]

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


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

NMe

Quia Ego Sic Dico.

Nee hoor, en wel om dezelfde reden dat het in een regexp fout gaat: in "<pre>foo<pre>bar</pre>baz</pre>" match je alleen de eerste <pre> met de eerste </pre>. De twee die niet bij elkaar horen dus. ;) Bovendien moet je die code ook nog eens in een functie gieten die het herhaaldelijk uitvoert om te zorgen dat hij alle paren matcht. ;)

Daarnaast is die -11 volgens mij een shortcut die je niet kan maken. Je moet -6 hebben. ;)

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


  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 26-11 20:53

Ventieldopje

I'm not your pal, mate!

De eerste </pre> hoe kom je daar bij? Als je goed leest staat er strrpos die dus reverse is, je match dus de eerste <pre> en de laatste</pre>

Wat betreft die -11 of -6 was ik niet helemaal zeker, -6 zou goed kunnen ;)
Bovendien moet je die code ook nog eens in een functie gieten die het herhaaldelijk uitvoert om te zorgen dat hij alle paren matcht.
Van php.net: str_replace — Replace all occurrences of the search string with the replacement string

Zoals je ziet vervangt hij alle< en > tekens ;)

[ Voor 40% gewijzigd door Ventieldopje op 06-04-2011 17:53 ]

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
Eerste met laatste pre:
code:
1
2
3
<pre>foo<pre>bar</pre>baz</pre>
Hallo wereld
pre>foo<pre>bar</pre>baz</pre>


[edit] Pagina 2 niet gezien. Voorbeeld code werkt nog steeds niet tho.

[ Voor 24% gewijzigd door ReenL op 06-04-2011 18:11 ]


  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 26-11 20:53

Ventieldopje

I'm not your pal, mate!

PHP:
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
29
30
<?php 

$raw = "<pre><?php echo 'GoT is top!';?><?php echo phpinfo(); ?></pre>"; 

// Alles tussen de eerste en laatste <pre> tags
$rawpre = substr($raw, strpos($raw, "<pre>") + 5, strrpos($raw, "</pre>") - 5); 

// methode 1: handmatig replacen (geen loop nodig)
$output = str_replace("<", "&lt;", $rawpre); 
$output = str_replace(">", "&gt;", $output); 

// methode 2:
$output2 = htmlspecialchars($rawpre);

echo("<b>Input:</b> " . htmlspecialchars($raw) . "<br />");
echo("<b>Output:</b> " . htmlspecialchars("<pre>" . $output . "</pre>") . "<br />");
echo("<b>Output methode 2:</b> " . htmlspecialchars("<pre>" . $output2 . "</pre>") . "<br />");

// vergelijk output van beide methodes
echo("<b>Output 1 == Output 2</b>: ");
if($output == $output2)
{
    echo("true");
}
else
{
    echo("false");
}

?>


Deze code werk zeker weten, test op: http://www.ventieldopje.net/test.php ;)

edit:was dus +5 en -5 :+

[ Voor 32% gewijzigd door Ventieldopje op 06-04-2011 19:42 ]

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


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

NMe

Quia Ego Sic Dico.

Ventieldopje schreef op woensdag 06 april 2011 @ 17:51:
De eerste </pre> hoe kom je daar bij? Als je goed leest staat er strrpos die dus reverse is, je match dus de eerste <pre> en de laatste</pre>
Daar had ik in de vluchtigheid inderdaad even overheen gelezen. Neemt niet weg dat je code dan nog steeds stuk gaat op een tekst met twee pre-blokken op hetzelfde niveau in het DOM zitten. Met nesting gaat je code dan inderdaad goed, maar met twee opeenvolgende, aparte pre's gaat het mis. :)
Van php.net: str_replace — Replace all occurrences of the search string with the replacement string

Zoals je ziet vervangt hij alle< en > tekens ;)
Klopt, en dat is dus meteen ook het probleem. :P

Als je zowel nesting als het verwerken van sibling elements goed af wil handelen zit je al snel naar een simpele stackbased parser te kijken. Lijkt me in dit specifieke geval wat overkill maar het kan een oplossing zijn. :)

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


  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 26-11 20:53

Ventieldopje

I'm not your pal, mate!

Dat is nou totaal niet wat ik uit zijn verhaal kan halen in de eerste post! Dit doet wat hij wil wat beschreven staat in zijn eerste post.

Als je siblings ook af wil handelen moet je gewoon een DOM tree opbouwen en die afwerken ja, maar de vraag is of dat nodig is, mijn voorbeeld code doet wat hij orgineel wou :)

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


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

NMe

Quia Ego Sic Dico.

Ventieldopje schreef op donderdag 07 april 2011 @ 16:33:
Dat is nou totaal niet wat ik uit zijn verhaal kan halen in de eerste post! Dit doet wat hij wil wat beschreven staat in zijn eerste post.

Als je siblings ook af wil handelen moet je gewoon een DOM tree opbouwen en die afwerken ja, maar de vraag is of dat nodig is, mijn voorbeeld code doet wat hij orgineel wou :)
Ja, want het is natuurlijk totaal ondenkbaar dat iemand dit wil doen in één tekst:

Voorbeeld 1:
foobar


Voorbeeld 2:
bazquux


8)7

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


  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 26-11 20:53

Ventieldopje

I'm not your pal, mate!

Tot voor kort ondenkbaar :+

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8

Pagina: 1