reguliere expressie match de 'binnenste' waardes?

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Carsten eng

carsten eng

21/09/2010 14:29:51
Quote Anchor link
Ik probeer matches te maken van stukjes html die beginnen met een H2 en eindigen met 'einde'. Maar in de eerste match zit meteen ook de titel die erboven staat, dat is niet de bedoeling. Ik wil de h2 die het dichtste bij 'einde' staat.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
$string = '<h2>bovenste</h2>';
$string .= '<h2> titel 1 </h2>';    
$string .= 'einde';
$string .= '<h2> titel 2 </h2>';    
$string .= 'einde';
$regex = "/<h2>(.*?)einde/is";

preg_match_all($regex, $string, $matches);
print_r($matches);
[/quote]
(ik gebruik de quote blokjes omdat er op dit forum blijkbaar dee code-blokjes zijn).

De output van bovenstaande is dit array:
[quote]Array
(
    [0] => Array
        (
            [0] => <h2>bovenste</h2><h2> titel 1 </h2>einde
            [1] => <h2> titel 2 </h2>einde
        )

    [1] => Array
        (
            [0] => bovenste</h2><h2> titel 1 </h2>

            [1] =>  titel 2 </h2>
        )

)


Dus deze gaat fout:
[0] => <h2>bovenste</h2><h2> titel 1 </h2>einde
dat moet zijn:
[0] => <h2> titel 1 </h2>einde

Hoe maak je een regex die dat doet?
Gewijzigd op 24/09/2010 10:43:11 door Bas IJzelendoorn
 
PHP hulp

PHP hulp

22/12/2024 18:56:16
 
Willem vp

Willem vp

21/09/2010 17:56:58
Quote Anchor link
Om te beginnen wil ik zeggen dat de reguliere expressie precies matcht wat 'ie zou moeten matchen, namelijk van de eerst gevonden h2-tag tot aan de eerste "einde".

Als de kans bestaat dat er meerdere h2-tags vóór het te matchen pattern staan, zul je dat expliciet moeten afvangen. Je krijgt dan iets als:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?
$regex
= "/(?:<h2>.*<\/h2>)?<h2>(.*?)einde/is";
?>


Er is misschien een elegantere oplossing, maar ik heb vandaag helaas geen tijd om daarover na te denken. Ik probeer er morgen op terug te komen.
 
Carsten eng

carsten eng

22/09/2010 10:05:13
Quote Anchor link
dank je wel.

met die code veranderd er wel iets, maar het eerste resultaat is anders, heel bizar.

dit is de output:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Array
(
    [0] => Array
        (
            [0] => <h2>bovenste</h2><h2> titel 1 </h2>einde
            [1] => <h2> titel 2 </h2>einde
        )

    [1] => Array
        (
            [0] =>  titel 1 </h2>

            [1] =>  titel 2 </h2>
        )

)


Dus die eerste is nog wel :
[0] => <h2>bovenste</h2><h2> titel 1 </h2>einde
maar in het 2de subarray geeft ie bij tussenliggende waardes wel de juiste content terug!?
[0] => titel 1 </h2>

Ik heb nog zitten zoeken en kwam dit tegen:
http://www.ibm.com/developerworks/library/os-php-regex2/index.html?ca=drs-&ca=dkw-php#list4
probeerde er iets als dit mee:
$regex = "/einde(?<=h2)/is";
maar dat doet niks.

Dank je wel. Hier kan ik mee verder!


Toevoeging op 22/09/2010 10:08:45:

O, nee. Hij ziet nu wel het juiste begin, maar gaat niet tot het einde.
 
Willem vp

Willem vp

23/09/2010 23:25:47
Quote Anchor link
De strings in het eerste subarray zijn de volledige stringdelen waarop de RE matcht; in het tweede subarray staan de strings van de matches die tussen de haakjes staan. Dat is dus precies zoals het hoort te werken ;-)

Het probleem met die lookbehind assertions die je van de IBM-site hebt geplukt, is dat de string 'einde' alleen matcht als meteen daarachter '<h2>' staat. Het werkt dus niet bij de laatste match of zelfs als er een spatie achter 'einde' staat.
 
Carsten eng

carsten eng

25/09/2010 09:00:27
Quote Anchor link
Het eerste array output de hele match, inclusief de zoekdingen. Het tweede de match zonder de zoekdingen.

Dan zou ik dit als output verwachten:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Array
(
    [0] => Array
        (
            [0] => <h2> titel 1 </h2>einde
            [1] => <h2> titel 2 </h2>einde
        )

    [1] => Array
        (
            [0] =>  titel 1 </h2>

            [1] =>  titel 2 </h2>
        )

)
 
Willem vp

Willem vp

25/09/2010 11:13:59
Quote Anchor link
Nee, want de reguliere expressie is /(?:<h2>.*<\/h2>)?<h2>(.*?)einde/
Het begin van de string matcht dus ook op het deel (?:<h2>.*<\/h2>)? en vandaar staat <h2>bovenste</h2> ook in Array[0][0].

Reguliere expressies zijn van nature greedy, dus ze proberen zoveel mogelijk te matchen. Als je verwachting niet klopt met de resultaten, dan ligt het meestal daaraan ;-)

Edit: Ik moest even zoeken, maar vorig jaar heb ik al eens in een reactie een verhaal geschreven over negative lookahead assertions. Eigenlijk is dat verhaal hier ook toe te passen: je wilt namelijk niet de string <h2> in je match hebben.

Ik laat het aan jou om het eerst zelf te proberen. Als je er niet uit komt, help ik je wel weer verder.
Gewijzigd op 25/09/2010 11:48:34 door Willem vp
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.