/ Forside / Teknologi / Udvikling / PHP / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
PHP
#NavnPoint
rfh 3959
natmaden 3372
poul_from 3310
funbreak 2700
stone47 2230
Jin2k 1960
Angband 1743
Bjerner 1249
refi 1185
10  Interkril.. 1146
finde links med preg_match_all regexp
Fra : Jacob Larsen


Dato : 30-01-04 21:03

Hej.

Jeg har efter en del besvær fundet ud af at det følgende virker til at finde
links i en html-fil. $text er html-filen og $matches er et array der skal
fyldes med resultater.

preg_match_all('|<a[^>]+>[^<]*</[^>]+>|U', $text, $matches);

Er der ikke nogen, der kan forklare mig hvorfor?

Det jeg ikke kan forstå er betydningen af de to |'er (lodrette streger) og
U'et til sidst. Det var noget jeg fik fra et eks. og uden dem virker det
ikke.

Jeg ved godt at | normalt betyder "eller" i disse regexp, men det kan jeg
ikke få til at passe her, og hvordan skulle det hænge sammen med U'et?
--
mvh. Jacob Larsen



 
 
Peter Brodersen (30-01-2004)
Kommentar
Fra : Peter Brodersen


Dato : 30-01-04 21:19

On Fri, 30 Jan 2004 21:02:53 +0100, "Jacob Larsen"
<jacobl@(((FJERNDETTE)))cs.auc.dk> wrote:

>Det jeg ikke kan forstå er betydningen af de to |'er (lodrette streger) og
>U'et til sidst. Det var noget jeg fik fra et eks. og uden dem virker det
>ikke.

preg_match*-funktionerne er taget fra perl, hvor et regulært udtryk
har en "delimiter". I perl kan man fx skrive:
   s/hund/kat/g
... for at udskifte "hund" med "kat" over det hele. Men adskillestegnet
(her "/") kan man selv vælge, så det her vil også virke:
   s|hund|kat|g

Grunden til at man vælger et andet tegn, er at man ellers kan komme
til at skulle escape adskillertegnet løbende. Så følgende er
identiske:

preg_match_all('!<a[^>]+>[^<]*</[^>]+>!U', $text, $matches);
preg_match_all('_<a[^>]+>[^<]*</[^>]+>_U', $text, $matches);
preg_match_all('/<a[^>]+>[^<]*<\/[^>]+>/U', $text, $matches);

Bemærk, at jeg i det nederste tilfælde bliver nødt til at sætte en \
foran / inde i udtrykket - ellers ville jeg have signalleret, at
udtrykket var afsluttet, og alt efter ville være forskellige flag.


Jeg må dog indrømme, at jeg ikke er så begejstret for PHPs indpakning
af det regulære udtryk - specielt når de samme udtryk i perl faktisk
kan skrives mere læsbare, og med mindre hovedpine. Så man har
grundlæggende set taget den komprimerede notation, og skal derefter få
brugeren til at opdele den i forskellige strings for tilsidst at
servere de strings til en funktion. Det ender let med at blive ét
gigantisk udtryk, bl.a. fordi man uden \Q og \E i perls
strenghåndtering samtidig kan risikere at skulle kaste preg_quote()
ind undervejs.

Så:
>   s_\b\Q$search\E\b_<b>$0</b>_gi
bliver til:
>   $string = preg_replace('_\b'.preg_quote($search).'\b_i','<b>$0</b>',$string);

Det nederste udtryk er rent faktisk blevet mindre gennemskueligt end
det øverste, og sværere at finde evt. tastefejl i.

--
- Peter Brodersen

Ebbesen for president!

Jacob Larsen (30-01-2004)
Kommentar
Fra : Jacob Larsen


Dato : 30-01-04 22:06

> Grunden til at man vælger et andet tegn, er at man ellers kan komme
> til at skulle escape adskillertegnet løbende. Så følgende er
> identiske:
>
> preg_match_all('!<a[^>]+>[^<]*</[^>]+>!U', $text, $matches);
> preg_match_all('_<a[^>]+>[^<]*</[^>]+>_U', $text, $matches);
> preg_match_all('/<a[^>]+>[^<]*<\/[^>]+>/U', $text, $matches);
>
> Bemærk, at jeg i det nederste tilfælde bliver nødt til at sætte en \
> foran / inde i udtrykket - ellers ville jeg have signalleret, at
> udtrykket var afsluttet, og alt efter ville være forskellige flag.

Ah ok, så de to |'er omkranser bare udtrykket og det sidste U er så et flag,
der fortæller at udtrykket skal opfattes non-greedy.

Jeg havde kigget på det med flag'et, men siden jeg aldrig har kodet perl og
ikke anede regexps skulle omkranses af delimiters kunne jeg ikke lige sætte
det ind i sammenhængen.

Mange tak for hjælpen. Nu kan jeg forstå hvad jeg laver igen.
--
mvh. Jacob Larsen



Søg
Reklame
Statistik
Spørgsmål : 177559
Tips : 31968
Nyheder : 719565
Indlæg : 6408934
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste