[php] string alleen tussen bepaalde tags replacen

Pagina: 1
Acties:
  • 107 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

  • sebas
  • Registratie: April 2000
  • Laatst online: 03-09 12:51
Ik wil voor mijn Content Managment System een functie maken die in de inhouds documenten ($content) bepaalde woorden aanklikbaar maakt, deze woorden staan in een array($smart)

Nu wil ik echter dat deze woorden alleen tussen de tags <H3> en </H3> worden ge-replaced. Ik zit al de hele dag met de regexes te kloten maar ik kom er maar niet uit.

(Verder moet ik ook nog voorkomen dat die string ($smart[$i]) binnen tags ge-replaced wordt, maar zover ben ik kennelijk nog niet. Als hier iemand een tip voor me heeft, ook graag...)


hier effe wat code:
PHP:
1
2
3
<?
$content = eregi_replace($smart[$i],$smart_replace,(ereg("<H3>(.*?)<\/H3>",$content)));
?>

...produceert deze error:

Warning: REG_BADRPT:erepetition-operator operand invalid in e:\webserver\master\layout\smartkeys.php on line 29

Ik heb zowel www.php.net/manual als ook PCRE en de GoTsearch geraadpleegt, maar kom er gewoon niet uit.

Misschien dat een l33t3 perl-er/php-er hier even na kan kijken en me met me neus op de fouten drukken?

Everyone complains of his memory, no one of his judgement.


Acties:
  • 0 Henk 'm!

Verwijderd

hmmm, dat kan ook met een str_replace volgens mij als ik het zo begrijp;

$content = str_replace("<H3>$smart</H3>", "<A href=''></A>", $content);

je gaat nu gewoon de hele array $smart langs tussen <H3></H3>'s; voor de links zou je dan eventueel nog een array kunnen maken met bv dezelfde key.

dus zo'n idee ongeveer:

$smart[] = "bla"; $smart_replace[] = "bla.html";

dan moet je je str_replace changen naar
$content = str_replace("<H3>$smart</H3>", "<A href='$smart_replace'>$smart</A>", $content);

ik hoop dat ik het goed begrepen heb :)
mzzl
maddo

Acties:
  • 0 Henk 'm!

  • sebas
  • Registratie: April 2000
  • Laatst online: 03-09 12:51
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?
$content = implode("",file ("test.htm"));



// smartlinks

unset($i);

$smart_keys = implode("",file ("smartkeys.txt"));

$smart = split(" \| ",$smart_keys);

$h3=split("<H3>",$content); // elements of $h3 beginning with <H3>

for ($i=0;$i<(count($h3));$i++) { 

    $h3[$i]=split("</H3>",$h3); // $h3[i][0] are content of <H3> tags

    $h3[$i][0]=split(" ",$h3[$i][0]); // $h3[i][0]array is content of <H3> tags, elements are words

    echo (count($h3[$i][0]))." words<BR>";

    for ($j=0;$j<(count($smart));$j++) { // array with keywords

        $smart_replace="<a href=index.php?search=".$smart[$j].">".$smart[$j]."</a>";

        for ($k=0;$k<(count($h3[$i][0]));$k++) {                    

            $h3[$i][0][$k] = ($h3[$i][0][$k]=$smart[$j]) ? $smart_replace : $h3[$i][0][$k];

            echo $h3[$i][0][$k];

        };

    };

    $h3[$i][0]=implode(" ", $h3[$i][0]);

    $h3[$i]=implode("</H3>", $h3[$i]);

}; //end for loop $i

$content=implode("<H3>", $h3);

echo $content;
?>

dit heb ik er nu van gemaakt.

Knap lelijk, he? Bovendien werkt ie nog niet, (maar dat mag eraan liggen dat ik nog niet de tijd had om het effe goed door te gaan...) Het lijkt me bovendien sterk dat zo'n boute code wel dedelijk langzamer is dan een geneste regel regex.

Misschien dat er toch nog iemand het foutje in mijn regex ziet...???

Everyone complains of his memory, no one of his judgement.


Acties:
  • 0 Henk 'm!

Verwijderd

Sebas: Ik wil een functie maken die in de inhouds documenten ($content) bepaalde woorden aanklikbaar maakt, deze woorden staan in een array($smart). Nu wil ik echter dat deze woorden alleen tussen de tags <H3> en </H3> worden ge-replaced. Ik zit al de hele dag met de regexes te kloten maar ik kom er maar niet uit.

Ik ga ervanuit dat woorden geen speciale tekens bevatten, dus geen preg_quote(), geen urlencode() en geen htmlentities(). This is left as an excercise for the reader...

Ok, Useless Hack™ #729... :P

Het eerste dat je nodig hebt is een regex voor je woorden (ik doet het zo omdat ik denk dat de vorm met een array in dit geval niet erg efficient is):
PHP:
1
2
3
4
5
6
7
<?
// (C) Arien@gathering.tweakers.net 



$smartRegex = '!\b(' . join('|', $smart) . ')\b!';
?>

Dan heb je natuurlijk de code nodig om tekst tussen je <h3>...</h3> tags te vervangen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
<?
$content = preg_replace(

    '!(<h3>)(.*?)(</h3>)!ise',

    "beSmart('\\1', '\\2', '\\3')",

    $content

);
?>

Het enige dat nu nog ontbreekt is de code van beSmart():
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?
function beSmart($pre, $text, $post) {

    global $smartRegex;

    $smartLink = preg_replace(

        $smartRegex,

        "<a href='index.php?word=\\1'>\\1</a>",

        $text

    );

    return $pre . $smartLink . $post;

}
?>

Enjoy.

Acties:
  • 0 Henk 'm!

  • sebas
  • Registratie: April 2000
  • Laatst online: 03-09 12:51
Arien,misschien overbodig om te zeggen, maar je bent een genius! Heb er redlijk wat hoofdpijn van gekregen...

Ik ga ervan uit dat ik als ik je naam in de sourcecode noem die functie mag gebruiken, anders hoor ik het wel!

[edit]
de functie is werkend te vinden op o.a. http://kun.dhs.org/master/

Everyone complains of his memory, no one of his judgement.


Acties:
  • 0 Henk 'm!

Verwijderd

Sebas: Arien,misschien overbodig om te zeggen, maar je bent een genius!

Bescheidenheid weerhoudt mij ervan dit te bevestigen. :P

Zo moeilijk is het trouwens niet. Als je de tekst tussen <h3>...</h3> hebt weet jij ook hoe je moet zoeken en vervangen zonder er hoofdpijn van te krijgen. Dus de eerste stap is zorgen dat je alleen met die tekst te maken hebt, dat gebeurt hier:
PHP:
1
2
3
4
5
6
7
8
9
10
11
<?
$content = preg_replace(

    '!(<h3>)(.*?)(</h3>)!ise',

    "beSmart('\\1', '\\2', '\\3')",

    $content

);
?>

beSmart() "ziet" alleen wat er tussen die tags staat (en de tags zelf als eerste en laatste argument, zodat je de functie ook voor andere tags kunt gebruiken) en vervangt je zoekwoorden door de links.
PHP:
1
2
3
<?
$smartRegex = '!\b(' . join('|', $smart) . ')\b!';
?>

maakt de regex voor je zoekwoorden. \b is een word boundary die voor en na je zoekwoord moet komen (anders matcht /foo/ ook /foobar/ en dat is neem ik aan niet de bedoeling).

Ik ga ervan uit dat ik als ik je naam in de sourcecode noem die functie mag gebruiken, anders hoor ik het wel!

Die (c) Arien@gathering.tweakers.net van mij is nooit serieus. ;) Dus met of zonder naam: als het voor jou werkt: it's all yours.

Acties:
  • 0 Henk 'm!

  • sebas
  • Registratie: April 2000
  • Laatst online: 03-09 12:51
Arien: jouw functie snap ik. Alleen wat ik niet snap is waarom mijn eerste regex niet werkt.
Is het omdat ie genest is?
Zitten er toch nog sysntaxfouten in?
Is dat gewoon een bug?

want dat
PHP:
1
2
3
<?
ereg("<H3>(.*?)<\/H3>",$content);
?>

haalt och alles tussen de H3 tags eruit en dat wordt dan door de eregi_replace gehaald, er zat een loop omheen die dat voor alle elementen uit $smart doet. :?

...maar ik ben allang blij dat het werkt natuurlijk! Bovendien is het ook een handig id om een functie binnen een regex te gebruiken...

Everyone complains of his memory, no one of his judgement.


Acties:
  • 0 Henk 'm!

Verwijderd

Sebas: Wat ik niet snap is waarom mijn eerste regex niet werkt. Is het omdat ie genest is? Zitten er toch nog sysntaxfouten in? Is dat gewoon een bug?

Die
PHP:
1
2
3
<?
ereg("<H3>(.*?)<\/H3>",$content);
?>

levert een integer op, namelijk om aan te geven of er een match was.
int ereg(string pattern, string string [, array regs]);
Voor wat jij wilt moet je tijdens het vervangen van tekst tussen <h3>...</h3> bepalen wat de vervangende tekst moet worden. Dat hangt er weer vanaf of er matches voor je woorden in voorkomen.

De oplossing die ik je gaf maakt de performance ook wat aangenamer omdat je maar een keer door de tekst loopt en maar 1 extra keer (in plaats van voor ieder woord) door je <h3>...</h3>. (Vandaar het zelf bouwen van de regex.)

Acties:
  • 0 Henk 'm!

  • Tom
  • Registratie: Juni 1999
  • Niet online

Tom

Pfff Arien heeft een iets hoger IQ ofzo dan mij :)

Acties:
  • 0 Henk 'm!

  • tomato
  • Registratie: November 1999
  • Niet online
Op Wednesday 14 March 2001 14:09 schreef Tom het volgende:
Pfff Arien heeft een iets hoger IQ ofzo dan mij :)
dan ik :P

Acties:
  • 0 Henk 'm!

Verwijderd

8-) Ik zit erop Tom. :P

Acties:
  • 0 Henk 'm!

  • sebas
  • Registratie: April 2000
  • Laatst online: 03-09 12:51
[aaargh}

Everyone complains of his memory, no one of his judgement.


Acties:
  • 0 Henk 'm!

  • sebas
  • Registratie: April 2000
  • Laatst online: 03-09 12:51
Arien
Die
[php]
<?
ereg("<H3>(.*?)<\/H3>",$content);
?>

[/php]
levert een integer op, namelijk om aan te geven of er een match was.
[..]


aargh, over het hoofd gezien...

maar is er een regex die de tekst die ik in de regex bepaal eruit filtert? want anders snap ik het verschil tussen preg_match en ereg niet.



De oplossing die ik je gaf maakt de performance ook wat aangenamer omdat je maar een keer door de tekst loopt en maar 1 extra keer (in plaats van voor ieder woord) door je <h3>...</h3>. (Vandaar het zelf bouwen van de regex.)

Dat is idd wel kewl, al vind ik het nogal onduidelijk waar nou de elementen van de smart-array doorgekeken worden, of gebeurt dat automatisch als ik er een array gebruik?

Everyone complains of his memory, no one of his judgement.


Acties:
  • 0 Henk 'm!

Verwijderd

Sebas: Is er een regex die de tekst die ik in de regex bepaal eruit filtert?

Je bedoelt zoals die $smartRegex die ik hierboven maak? :?

Want anders snap ik het verschil tussen preg_match en ereg niet.

preg_match() is veel krachtiger dan ereg().

Ik vind het nogal onduidelijk waar nou de elementen van de smart-array doorgekeken worden, of gebeurt dat automatisch als ik er een array gebruik?

Als je een array gebruikt wordt voor elk van de elementen van het array de regex in dat element uitgevoerd.
Wat ik doe is een regex maken die als alternatieven de woorden heeft die je wilt matchen met wordboundaries (die \b) eromheen.

Was dat wat je wilde weten? :)

Acties:
  • 0 Henk 'm!

  • jurriaan
  • Registratie: Januari 2000
  • Laatst online: 31-03 02:37
Het verschil tussen preg en ereg zit hem in Perl complient of POSIX :?

preg zit erin voor de mensen die het leuk vinden om regexps te schrijven :D

Wees verantwoordelijk voor je eigen daden


Acties:
  • 0 Henk 'm!

  • sebas
  • Registratie: April 2000
  • Laatst online: 03-09 12:51
Arien:

... dat was het inderdaad wat ik wilde weten.

Ik wil voor datzelfde CMS ook nog een edit functie schrijven. Deze edit functie moet in principe aan de hand van de <Hx> tags een formulier opbouwen, daarin de inhoud van de verschillende tags pleuren en weer in de goede volgorde terugsturen naar de server.

Ik denk dat ik op die manier er wel uitkom, nogmaals bedankt!

Everyone complains of his memory, no one of his judgement.


Acties:
  • 0 Henk 'm!

Verwijderd

jurriaan: Het verschil tussen preg en ereg zit hem in Perl compliant of POSIX :?

preg_* zijn regexen zoals Perl ze zou doen (voor bepaalde iets verouderde versie van Perl).
ereg* zal is POSIX extended volgens de manual. Ik gebruik het bar weinig.

preg zit erin voor de mensen die het leuk vinden om regexps te schrijven :D

:D

Of omdat wat je wilt niet (of niet handig) kan met ereg*

Acties:
  • 0 Henk 'm!

Verwijderd

Sebas: Ik denk dat ik op die manier er wel uitkom, nogmaals bedankt!

Succes. Ik hoor het wel als je er niet uit komt. :)

Acties:
  • 0 Henk 'm!

  • sebas
  • Registratie: April 2000
  • Laatst online: 03-09 12:51
hehe, inderdaad.

maar anders ook wel denk ik :)

Everyone complains of his memory, no one of his judgement.


Acties:
  • 0 Henk 'm!

  • jurriaan
  • Registratie: Januari 2000
  • Laatst online: 31-03 02:37
Ik gebruik ook alleen preg, al was het omdat
a) mijn boekje niet over POSIX gaat
b) POSIX veel te veel vieze backslashes gebruikt
c) Ik dan regelrecht regexps uit mijn Perlscripts kan overnemen :D

Wees verantwoordelijk voor je eigen daden

Pagina: 1