[PHP] preg_match _all resultaat onregelmatig: waarom?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Hoppie
  • Registratie: Februari 2001
  • Niet online
Ik heb de volgende input voor een preg_match_all:
HTML:
1
2
3
4
5
disp.php?cache=no&ID=1556" class=news>Lancia onthult Granturismo Stilnovo<
disp.php?cache=no&ID=1560" class=normal>Nieuwe CDI-motoren voor C-klasse<
disp.php?cache=no&ID=1550" class=normal>Fris front voor Sebring<
disp.php?cache=no&ID=1559" class=normal>Kangoo voor het ruige werk<
disp.php?cache=no&ID=1555" class=normal>Spectaculaire Seat Cupra GT<

Nu wil ik met de preg_match_all functie de titel uit deze link filteren. Daarvoor gebruik ik de volgende reguliere expressie:
PHP:
1
2
3
$regexp = "/>(.*?)</i";
preg_match_all($regexp, $link, $arrayoftitles);
echo $arrayoftitles[1][0]."\n";

Waarbij $link één van de bovenstaande html strings bevat.
Probleem is nu dat deze oplossing werkt, echter alleen voor de eerste string!
Resultaat is:
HTML:
1
Lancia onthult Granturismo Stilnovo

Bij de andere input strings levert deze oplossing geen match op, echter als ik het volgende doe:
PHP:
1
2
3
$regexp = "/>(.*?)</i";
preg_match_all($regexp, $link, $arrayoftitles);
echo $arrayoftitles[1][1]."\n";

Dan is het verhaal precies omgekeerd! Het resultaat is dan:
HTML:
1
2
3
4
Nieuwe CDI-motoren voor C-klasse
Fris front voor Sebring
Kangoo voor het ruige werk
Spectaculaire Seat Cupra GT

Nu slaat ie dus de eerste weer over.
Kan iemand mij uitleggen waardoor dit komt? Ik heb al (natuurlijk) op GoT gezocht (en de FAQ van drm gelezen) en uiteraard op php.net (PCRE), maar kan de oplossing niet vinden. :'(

Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Doe sowieso es print_r($arrayoftitles); ipv echo van 1 entry...

Acties:
  • 0 Henk 'm!

  • Hoppie
  • Registratie: Februari 2001
  • Niet online
ACM schreef op 27 April 2003 @ 13:04:
Doe sowieso es print_r($arrayoftitles); ipv echo van 1 entry...
Resultaat:
HTML:
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
disp.php?cache=no&ID=1556" class=news>Lancia onthult Granturismo Stilnovo< Array
(
    [0] => Array
        (
            [0] => >Lancia onthult Granturismo Stilnovo<
        )

    [1] => Array
        (
            [0] => Lancia onthult Granturismo Stilnovo
        )

)
disp.php?cache=no&ID=1560" class=normal>Nieuwe CDI-motoren voor C-klasse< Array
(
    [0] => Array
        (
            [0] => ><
            [1] => >Nieuwe CDI-motoren voor C-klasse<
            [2] => ><
        )

    [1] => Array
        (
            [0] => 
            [1] => Nieuwe CDI-motoren voor C-klasse
            [2] => 
        )

)
disp.php?cache=no&ID=1550" class=normal>Fris front voor Sebring< Array
(
    [0] => Array
        (
            [0] => ><
            [1] => >Fris front voor Sebring<
            [2] => ><
        )

    [1] => Array
        (
            [0] => 
            [1] => Fris front voor Sebring
            [2] => 
        )

)
disp.php?cache=no&ID=1559" class=normal>Kangoo voor het ruige werk< Array
(
    [0] => Array
        (
            [0] => ><
            [1] => >Kangoo voor het ruige werk<
            [2] => ><
        )

    [1] => Array
        (
            [0] => 
            [1] => Kangoo voor het ruige werk
            [2] => 
        )

)
disp.php?cache=no&ID=1555" class=normal>Spectaculaire Seat Cupra GT< Array
(
    [0] => Array
        (
            [0] => ><
            [1] => >Spectaculaire Seat Cupra GT<
            [2] => ><
        )

    [1] => Array
        (
            [0] => 
            [1] => Spectaculaire Seat Cupra GT
            [2] => 
        )

)

OK, ik zie het verschil, maar ik snap het niet. Ik gebruik dezelfde reguliere expressie en de strings zijn ook vrijwel gelijk en toch levert het verschillende resultaten.
Ik heb overigens class=news als eens gewijzigd in class=normal, maar dat leverde niets op.

Acties:
  • 0 Henk 'm!

  • Hoppie
  • Registratie: Februari 2001
  • Niet online
preg_match_all @ php.net:
PREG_PATTERN_ORDER
Orders results so that $matches[0] is an array of full pattern matches, $matches[1] is an array of strings matched by the first parenthesized subpattern, and so on.


<?php
preg_match_all ("|<[^>]+>(.*)</[^>]+>|U",
"<b>example: </b><div align=left>this is a test</div>",
$out, PREG_PATTERN_ORDER);
print $out[0][0].", ".$out[0][1]."\n";
print $out[1][0].", ".$out[1][1]."\n";
?>


This example will produce: <b>example: </b>, <div align=left>this is a test</div>
example: , this is a test

So, $out[0] contains array of strings that matched full pattern, and $out[1] contains array of strings enclosed by tags.
ff opgesnort op php.net.
Hieruit begrijp ik het volgende:
- in $array[0][x] vind ik de matches inclusief het opgegeven patroon
- in $array[1][x] vind ik de matches exclusief het opgegeven patroon

Als ik nu naar de resultaten van mijn reguliere expressie kijk, dan snap ik niet hoe
er >< als match inclusief patroon kan zijn. Die vind ik nergens terug in m'n input string.

Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Ik snap idd ook niet waarom die [nohtml]><[nohtml] gematched moet worden...

Sterker nog:
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
more test.php
<?
$link = 'disp.php?cache=no&ID=1556" class=news>Lancia onthult Granturismo Stilno
vo<
disp.php?cache=no&ID=1560" class=normal>Nieuwe CDI-motoren voor C-klasse<
disp.php?cache=no&ID=1550" class=normal>Fris front voor Sebring<
disp.php?cache=no&ID=1559" class=normal>Kangoo voor het ruige werk<
disp.php?cache=no&ID=1555" class=normal>Spectaculaire Seat Cupra GT<';

$regexp = "/>(.*?)</i";
preg_match_all($regexp, $link, $arrayoftitles);
print_r($arrayoftitles);
?>

php test.php
Array
(
    [0] => Array
        (
            [0] => >Lancia onthult Granturismo Stilnovo<
            [1] => >Nieuwe CDI-motoren voor C-klasse<
            [2] => >Fris front voor Sebring<
            [3] => >Kangoo voor het ruige werk<
            [4] => >Spectaculaire Seat Cupra GT<
        )

    [1] => Array
        (
            [0] => Lancia onthult Granturismo Stilnovo
            [1] => Nieuwe CDI-motoren voor C-klasse
            [2] => Fris front voor Sebring
            [3] => Kangoo voor het ruige werk
            [4] => Spectaculaire Seat Cupra GT
        )

)


Bij mij doet ie het prima, welke php-versie gebruik je?

Acties:
  • 0 Henk 'm!

  • Hoppie
  • Registratie: Februari 2001
  • Niet online
Ik draai PHP 4.2.1 op FreeSCO.
Overigens maak ik er niet eerst één grote string van. Ga ik nu ff proberen.
De strings staan in een array dat resulteerd uit een eerdere preg_match_all.

Acties:
  • 0 Henk 'm!

  • Hoppie
  • Registratie: Februari 2001
  • Niet online
Na implosie van de resultaten van de eerste preg_match_all:
HTML:
1
2
3
4
5
disp.php?cache=no&ID=1556" class=news>Lancia onthult Granturismo Stilnovo<
 disp.php?cache=no&ID=1560" class=normal>Nieuwe CDI-motoren voor C-klasse<
 disp.php?cache=no&ID=1550" class=normal>Fris front voor Sebring< disp.php?
cache=no&ID=1559" class=normal>Kangoo voor het ruige werk< disp.php?
cache=no&ID=1555" class=normal>Spectaculaire Seat Cupra GT
(paar \n 's toegevoegd om de layout niet volledig te verprutsen....)

Levert:
PHP:
1
2
3
    $regexp = "/>(.*?)</i";
    preg_match_all($regexp, $links, $arrayoftitles);
    print_r ($arrayoftitles);

dit op:
HTML:
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
Array
(
    [0] => Array
        (
            [0] => >Lancia onthult Granturismo Stilnovo<
            [1] => ><
            [2] => >Nieuwe CDI-motoren voor C-klasse<
            [3] => ><
            [4] => ><
            [5] => >Fris front voor Sebring<
            [6] => ><
            [7] => ><
            [8] => >Kangoo voor het ruige werk<
            [9] => ><
            [10] => ><
            [11] => >Spectaculaire Seat Cupra GT<
            [12] => ><
        )

    [1] => Array
        (
            [0] => Lancia onthult Granturismo Stilnovo
            [1] => 
            [2] => Nieuwe CDI-motoren voor C-klasse
            [3] => 
            [4] => 
            [5] => Fris front voor Sebring
            [6] => 
            [7] => 
            [8] => Kangoo voor het ruige werk
            [9] => 
            [10] => 
            [11] => Spectaculaire Seat Cupra GT
            [12] => 
        )

)

Het probleem blijft dus. Snap niks van.... ;(

[ Voor 48% gewijzigd door Hoppie op 27-04-2003 14:16 . Reden: tiepvoutje.... ]


Acties:
  • 0 Henk 'm!

  • Hoppie
  • Registratie: Februari 2001
  • Niet online
Volledige code:
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
<?php

echo "<pre>";
$url = "urltest.html";//"http://www.autoweek.nl/index.php"; 

$contents = Implode("", File($url)); 

$regexp = "/<b><a href=\"news(.*?)\/a><\/b>/i";
preg_match_all($regexp, $contents, $arrayoflinksandtitles); 

while (list(,$link) = each($arrayoflinksandtitles[1]))
{
    echo $link." ";
    $regexp = "/&ID=(.*?)\"/i";
    preg_match_all($regexp, $link, $arrayoflinks);
    $regexp = "/>(.*?)</i";
    preg_match_all($regexp, $link, $arrayoftitles);
    echo $arrayoftitles[1][0]."\n";
}

$regexp = "/<td><a href=\"news(.*?)\/a><\/td>/i";
preg_match_all($regexp, $contents, $arrayoflinksandtitles); 

while (list(,$link) = each($arrayoflinksandtitles[1]))
{
    echo $link." ";
    $regexp = "/&ID=(.*?)\"/i";
    preg_match_all($regexp, $link, $arrayoflinks);
    $regexp = "/>(.*?)</i";
    preg_match_all($regexp, $link, $arrayoftitles);
    echo $arrayoftitles[1][0]."\n";
}
echo "</pre>";
?>

Overigens werkt het tweede deel (vanaf regel 20) wel foutloos.

[ Voor 19% gewijzigd door Hoppie op 27-04-2003 14:24 ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Als ik kijk wat hij ophaalt bij autoweek, dan ziet dat er zo uit:
HTML:
1
2
3
4
5
disp.php?cache=no&ID=1556" class=news>Lancia onthult Granturismo Stilnovo< Lancia onthult Granturismo Stilnovo
disp.php?cache=no&ID=1560" class=normal><font size=2>Nieuwe CDI-motoren voor C-klasse</font>< 
disp.php?cache=no&ID=1550" class=normal><font size=2>Fris front voor Sebring</font>< 
disp.php?cache=no&ID=1559" class=normal><font size=2>Kangoo voor het ruige werk</font>< 
disp.php?cache=no&ID=1555" class=normal><font size=2>Spectaculaire Seat Cupra GT</font><


Er staan dus nog <font> tags omheen..

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Hoppie
  • Registratie: Februari 2001
  • Niet online
Ik heb het probleem gevonden:
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
            [0] => <B><A HREF="newsdisp.php?cache=no&ID=1556" class=news>Lancia onthult Granturismo Stilnovo</a></B>
            [1] => <B><A HREF="newsdisp.php?cache=no&ID=1560" class=normal><font size=2>Nieuwe CDI-motoren voor C-klasse</font></a></B>
            [2] => <B><A HREF="newsdisp.php?cache=no&ID=1550" class=normal><font size=2>Fris front voor Sebring</font></a></B>
            [3] => <B><A HREF="newsdisp.php?cache=no&ID=1559" class=normal><font size=2>Kangoo voor het ruige werk</font></a></B>
            [4] => <B><A HREF="newsdisp.php?cache=no&ID=1555" class=normal><font size=2>Spectaculaire Seat Cupra GT</font></a></B>
            [5] => <td><A HREF="newsdisp.php?cache=no&ID=1554" class=side>Renault Mégane sedan komt wél</a></td>
            [6] => <td><A HREF="newsdisp.php?cache=no&ID=1546" class=side>Gemodificeerde Seat Leon Cupra R</a></td>
            [7] => <td><A HREF="newsdisp.php?cache=no&ID=1549" class=side>Nieuwe Njoy-versies van Opel</a></td>
            [8] => <td><A HREF="newsdisp.php?cache=no&ID=1551" class=side>Nieuwe instapper Audi allroad</a></td>
            [9] => <td><A HREF="newsdisp.php?cache=no&ID=1535" class=side>Isuzu met directe inspuiting</a></td>
            [10] => <td><A HREF="newsdisp.php?cache=no&ID=1548" class=side>Renault onthult Mégane Grand Tour</a></td>
            [11] => <td><A HREF="newsdisp.php?cache=no&ID=1547" class=side>Peugeot 307 SW Trekauto 2003</a></td>
            [12] => <td><A HREF="newsdisp.php?cache=no&ID=1553" class=side>Nieuwe diesel voor Grand Vitara</a></td>
            [13] => <td><A HREF="newsdisp.php?cache=no&ID=1552" class=side>Zespersoons Mazda MPV Active</a></td>
            [14] => <td><A HREF="newsdisp.php?cache=no&ID=1521" class=side>Lincoln Navigator K concept</a></td>
            [15] => <td><A HREF="newsdisp.php?cache=no&ID=1534" class=side>Nissan Pathfinder Armada</a></td>
            [16] => <td><A HREF="newsdisp.php?cache=no&ID=1533" class=side>Nissan 350Z Roadster onthuld</a></td>

Dit is de originele html-code waarop ik m'n regexen heb los gelaten. Af en toe komt er een <font size=2> tag tussendoor zetten die roet in het eten gooit.
De regex om de titels eruit te filteren is als volgt geworden:
PHP:
1
$regexp = "/(s>|2>|e>)+(.*?)</";

Hierbij wordt dus naar s>, 2> en e> gezocht als begin van de titel string.
En dat werkt! :)

Acties:
  • 0 Henk 'm!

  • Hoppie
  • Registratie: Februari 2001
  • Niet online
crisp schreef op 27 april 2003 @ 15:16:
knip....
Er staan dus nog <font> tags omheen..
Je was me juist voor crisp!
Toch bedankt voor jullie suggesties! Vooral de print_r was zeer behulpzaam!

Acties:
  • 0 Henk 'm!

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09 23:18

djc

Heb je http://xml.xavamedia.nl/nml/autoweek al eens gezien? :)

Rustacean


Acties:
  • 0 Henk 'm!

  • Hoppie
  • Registratie: Februari 2001
  • Niet online
Jazeker! Ik heb je zelfs gevraagd die voor me te maken!
Ik wilde alleen 's kijken of ik het ook zelf kon en het is me gelukt.
Overigens is bovenstaande script niet hetgeen wat ik nu uiteindelijk heb, ik gooi de links en de titels in een twee dimensionaal array en sorteer vervolgens op de links. Daarmee worden de titels op chronologische volgorde getoond. Nog net iets mooier dan jouw oplossing.... ;)

Acties:
  • 0 Henk 'm!

  • nljuggler
  • Registratie: Juni 2002
  • Laatst online: 09-11-2021
Hoppie schreef op 27 April 2003 @ 15:16:
Ik heb het probleem gevonden:

-knip-

Dit is de originele html-code waarop ik m'n regexen heb los gelaten. Af en toe komt er een <font size=2> tag tussendoor zetten die roet in het eten gooit.
De regex om de titels eruit te filteren is als volgt geworden:
PHP:
1
$regexp = "/(s>|2>|e>)+(.*?)</";

Hierbij wordt dus naar s>, 2> en e> gezocht als begin van de titel string.
En dat werkt! :)
Niet dat de nu gebruikte code niet werkt, maar als je de asterisk (0 of meer karakters) in je code had vervangen voor een plusje (1 of meer karakters) was je ook klaar geweest. De functie van het vraagteken in de expressie ontgaat me ook geheel.

PHP:
1
$regexp = "/>(.+)</";

If Newton was a juggler, he would have caught the apple...


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

nljuggler schreef op 30 April 2003 @ 00:12:
[...]


Niet dat de nu gebruikte code niet werkt, maar als je de asterisk (0 of meer karakters) in je code had vervangen voor een plusje (1 of meer karakters) was je ook klaar geweest. De functie van het vraagteken in de expressie ontgaat me ook geheel.

PHP:
1
$regexp = "/>(.+)</";
Het vraagteken maakt de matching ungreedy. Stel dat je dit in 1 string hebt staan:

'blaatiebloep > enzovoorts < en nog een keer > en nog iets meer < enzo'

en je gebruikt jouw regexp, dan is dit je match:

'> enzovoorts < en nog een keer > en nog iets meer <'

snappie?

zo doet 'ie het inderdaad wel goed:

PHP:
1
$regexp = "/>(.+?)</";


of je moet de /U modifier gebruiken:

PHP:
1
$regexp = "/>(.+)</U";

[ Voor 43% gewijzigd door crisp op 30-04-2003 00:36 ]

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Hoppie
  • Registratie: Februari 2001
  • Niet online
crisp schreef op 30 April 2003 @ 00:20:
[...]

Het vraagteken maakt de matching ungreedy. ...knip....
Dat is inderdaad de reden waarom ik het vraagteken erbij heb staan.
Ik heb deze informatie onder andere hier gevonden.
Uiteraard ben ik ook door schade en schande rijk geworden en had eerst het probleem dat m'n regex té greedy was.

[ Voor 15% gewijzigd door Hoppie op 01-05-2003 19:18 ]

Pagina: 1