Avatar billede drbean Nybegynder
16. juni 2006 - 19:09 Der er 30 kommentarer og
1 løsning

Hjælp til PREG

Mit evig tilbage vendende problem. PREG.

Har et link der ser sådan her ud:

<a href="http://mydoamin.dk" title="MyDomain">Dette er mit domæne</a>

Nu vil jeg meget gerne have teksten "Dette er mit domæne" ud. Kan ikke helt gennemskue det.

Kunne gøre sådan her:
preg_match('/>[^<].*</', $subject, $aRes)

Men så ville jeg også få >< med. Nogen der har nogen ideer? Ved godt jeg kan bruge str_replace, men det er ikke optimalt.
Avatar billede nielle Nybegynder
16. juni 2006 - 19:17 #1
Måske:

preg_match("/<a [^>]*>(.*?)<\/a>/i", "$1", $aRes);
Avatar billede nielle Nybegynder
16. juni 2006 - 19:20 #2
Vrøvl ... se bort fra den!

Prøv dette i stedet:

preg_match("/<a [^>]*>(.*?)<\/a>/i", $subject, $aRes);
echo $aRes[1];
Avatar billede nielle Nybegynder
16. juni 2006 - 19:23 #3
Eller du kan bruge preg_replace (hvilket var det jeg kagede rundt i ovenfor):

$subject = preg_replace("/<a [^>]*>(.*?)<\/a>/i", "$1", $subject);
Avatar billede drbean Nybegynder
16. juni 2006 - 19:23 #4
desværre, den retunere det hele...
Avatar billede drbean Nybegynder
16. juni 2006 - 19:24 #5
sry.. så kun den første kommentar.. tester lige igen
Avatar billede drbean Nybegynder
16. juni 2006 - 19:28 #6
1000 tak for hjælpen.

preg_replace virker. Men hvorfor? (.*?) er det den del den retunere?

Og smid lige et svar.
Avatar billede nielle Nybegynder
16. juni 2006 - 19:32 #7
16/06-2006 19:20:40 burde nu også virke. Har du afprøvet den?

Men hvorfor?>

Et ()-par "fanger" det som er indenfor i parenteserne, altså det som matcher .*?. Det, som er, fanget kan efterfølgende hentes frem som $1. Hvis der er et parentespar mere så fanger dette som $2, det næste igen som $3, osv.

Var det forklaring nok, eller er der mere du er lidt usikker på?
Avatar billede gizmo-gizmo Nybegynder
16. juni 2006 - 19:35 #8
nielle: jeg har lige et spørgsmål (hvis det ikke gør noget :). Hvad laver det spørgsmålstegn efter ".*"  ? jeg er udmærket klar over at .* betyder hvilket som helst tegn optræder 0 eller flere gange. Det virker og giver mening i sig selv, men hvad med ?  (som jo betyder might/might not.. agtigt)
Avatar billede drbean Nybegynder
16. juni 2006 - 19:37 #9
Jeg kan simpelhen ikke få 16/06-2006 19:20:40 til at virke. Den med $1, bruges det kun på preg_replace, eller burde det også virke på match?
Avatar billede drbean Nybegynder
16. juni 2006 - 19:41 #10
Kan jeg så lave noget i stil med:
$subject = preg_replace("/<a [^>]* title="(.*?)">(.*?)<\/a>/i", "$1","$2", $subject);

Og bagefter echo dem ud som $1 og $2?
Avatar billede gizmo-gizmo Nybegynder
16. juni 2006 - 19:42 #11
drbean: det her virker altså lige ud:

$subject = "<a href=\"http://mydoamin.dk\" title=\"MyDomain\">Dette er mit domæne</a>";
preg_match("/<a [^>]*>(.*?)<\/a>/i", $subject, $aRes);
echo $aRes[1];
Avatar billede nielle Nybegynder
16. juni 2006 - 19:46 #12
> Jeg kan simpelhen ikke få 16/06-2006 19:20:40 til at virke.

Hmmm, mystisk.

> Den med $1, bruges det kun på preg_replace, eller burde det også virke på match?

Nej, $1 er noget noget sludder i forbindelse med match.

> nielle: jeg har lige et spørgsmål (hvis det ikke gør noget :). Hvad laver det spørgsmålstegn efter ".*"  ?

Spørg løs :^)

Normalt vil ".*" matche "nul eller flere tegn", men den vil gøre det "grådigt" (kaldes greedy matching), dvs. at den vil matche så meget som den kan komme til. Dette kan være et problem hvis der er flere ting som kan matches:

$subject = "... <a href="xxx" title="xxx">tekst 1</a> ... <a href="yyy" title="yyy">tekst 2</a> ...";

Uden et ?-tegn ville vores preg_replace() returnere:

$subject = "tekst 1</a> ... <a href="yyy" title="yyy">tekst 2";

Den tager så meget som den kan komme til (prøv selv efter).

Med ?-tegnet gøres matchningen doven (lazy matching), og den stopper når den kan:

$subject = "tekst 1";
Avatar billede drbean Nybegynder
16. juni 2006 - 19:47 #13
ja, det har du ret i. Ved ikke hvad jeg sad og lavede før. Så sent er det da heller ikke ;-)

1000 tak for hjælpen
Avatar billede jakobdo Ekspert
16. juni 2006 - 19:49 #14
Nielle, du bruger [^>] er der den store forskel på om man laver det sådan her:

preg_match('/<a.*?>(.*?)<\/a>/i', $subject, $aRes);
Avatar billede drbean Nybegynder
16. juni 2006 - 19:49 #15
1000 tak til jer begge. Alt jeg mangler inde for programmering er regulære udtryk. Syntes det er noget hat at lære. Men tror jeg er ved at forstå det nu. 1000 tak
Avatar billede nielle Nybegynder
16. juni 2006 - 19:49 #16
16/06-2006 19:41:32>

Nej, der ville du have behov for preg_match(). Det bedste du kunne gøre med preg_replace() ville være:

$subject = preg_replace("/<a [^>]* title="(.*?)">(.*?)<\/a>/i", "$1,$2", $subject);

Med preg_match() ville løsningen se sådan her ud:

$subject = preg_match("/<a [^>]* title="(.*?)">(.*?)<\/a>/i", $subject, $aRes);
echo $aRes[1] . <br>;
echo $aRes[2] . <br>;
Avatar billede jakobdo Ekspert
16. juni 2006 - 19:51 #17
drbean: Prøv at kig på programmet www.regexbuddy.com
Avatar billede nielle Nybegynder
16. juni 2006 - 19:51 #18
16/06-2006 19:49:15> Nej, men der kan jo også sagtens være mange løsninger på et givet problem.
Avatar billede jakobdo Ekspert
16. juni 2006 - 19:52 #19
Nielle:
Din løsning burde vel for godt ordens skyld være:

if(preg_match("/<a [^>]* title="(.*?)">(.*?)<\/a>/i", $subject, $aRes))
{
echo $aRes[1] . '<br />';
echo $aRes[2] . '<br />';
}
else
{
echo 'Intet fundet<br />';
}
Avatar billede nielle Nybegynder
16. juni 2006 - 19:53 #20
16/06-2006 19:52:24> Er for så vidt fuldstændig enig.

drbean>

Jeg kan helt klart anbefale dig denne guide udi regex:

http://www.regularexpressions.info/
Avatar billede drbean Nybegynder
16. juni 2006 - 19:54 #21
16/06-2006 19:51:05> Sidder faktisk med det program. Men jeg vil også gerne forstå lidt af det. Og kunne ikke rigtig lure den med at retunere en del af strengen. Men ellers et godt program
Avatar billede gizmo-gizmo Nybegynder
16. juni 2006 - 19:56 #22
nielle: ahh, tak... greedyness og lazyness. Jeg er ikke kommet dertil i masteringen regular expressions endnu, så jeg undrede mig bare lidt ;)
Avatar billede nielle Nybegynder
16. juni 2006 - 20:14 #23
16/06-2006 19:49:15>

Der er faktisk en forskel. Performancemæssigt er mønster 1) mere effektivt end 2):

1) "/<a [^>]*>(.*?)<\/a>/i"
2) "/<a.*?>(.*?)<\/a>/i"

Måling - godt nok i C# i stedet for PHP - af 1.000.000 matchinger:

1) 5,7 sek
2) 9,0 sek

Og for mønsteret:

3) "/<a .*?>(.*?)<\/a>/i"

8,7 sek (men svingende op til 9,0 sek for mange af mine målinger).

Jeg gætter på at det er den lazy matching der skal på i "<a.*?>" som koster performance. Den undgås i hvertfald med "<a [^>]*>". Men det er kun et gæt.
Avatar billede gizmo-gizmo Nybegynder
16. juni 2006 - 20:35 #24
nielle: Jeg tror du har helt ret i at det er måden hvorpå lazy matching fungerer som koster performance. Det fungerer åbenbart lidt på samme måde som greedy matching - bare forfra i stedet for bagfra (bagfra hvor den først matcher alt hvad den kan, finder ud af at næste led ikke matcher, tager så ét tegn mindre og prøver igen.. og igen.. og igen indtil der kommer et samlet match). Med [^>]* kan den jo bare tage tegn for tegn og sige: er det her tegn anderledes end >, så godt... agtigt ;)
Avatar billede drbean Nybegynder
16. juni 2006 - 20:38 #25
hmm... troede jeg havde forstået det, men jeg kan ikke hente href ud på denne måde
preg_match('/<a [^>]* href="(.*?)">.*?<\/a>/i', $subject, $aRes);

nogen ide hvorfor? Eller er det mig der er helt gal på den.
Avatar billede nielle Nybegynder
16. juni 2006 - 20:44 #26
Der er måske fordi at dit mønster ikke tager højde for den title-attribut som kommer efter href-attrributten?
Avatar billede drbean Nybegynder
16. juni 2006 - 20:47 #27
det burde ikke være det, da ikke alle link har en title på. men har prøvet sådan her:
preg_match("/<a [^>]* href=\"(.*?)\" [^>]*>.*?<\/a>/i", $sAHref, $aRes);
Avatar billede nielle Nybegynder
16. juni 2006 - 20:50 #28
Husk på at [^>]* også matcher mellemrum:

preg_match("/<a [^>]*href=\"(.*?)\"[^>]*>.*?<\/a>/i", $sAHref, $aRes);
Avatar billede nielle Nybegynder
16. juni 2006 - 20:52 #29
Forresten, hvis du ikke mere har brug for at kunne hente "Dette er mit domæne" ud af din tekst, så kan mønstret effektiviseres til:

preg_match("/<a [^>]*href=\"(.*?)\"[^>]*>/i", $sAHref, $aRes);

- eller endda til:

preg_match("/ href=\"(.*?)\"/i", $sAHref, $aRes);
Avatar billede drbean Nybegynder
16. juni 2006 - 20:53 #30
fair nok... tak for hjælpen endnu engang... skriv hvis du vil have flere point for hjælpen
Avatar billede nielle Nybegynder
16. juni 2006 - 20:54 #31
Nej tak :^)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester