[php] Regular Expression lijkt niet altijd te werken

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

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Dag allen,

Ik ben een groot deel van de avond bezig met de volgende, behoorlijk eenvoudige regular expression voor Preg_match. Idee is dat ik een string uit de database in een array krijg en ik zo de volgorde kan wijzigen.

Als volgt.
PHP:
1
2
3
4
5
<?
if (preg_match("#(.*)\\[module:(.*)\\](.*)#",  $row->content, $regs)) {
    print_r($regs);
 } 
?>


Met als content: Hallo, dit is de module die uiteindelijk ge-include moet worden: [module:test] restje tekst

In mijn zoektoch op het internet kwam ik "Regular Expression Testscripts" tegen, hier kon ik de pattern en de tekst invullen, en alles werkte prima, en kreeg netjes drie subsets terug. Hoe kan het dat het in mijn php code PHP niet zo gaat?

Acties:
  • 0 Henk 'm!

  • Stoffel
  • Registratie: Mei 2001
  • Laatst online: 19-09 10:17

Stoffel

Engineering the impossible

Wat krijg je dan wel terug?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik krijg hem bijna, maar dus niet de eerste subset, vreemd genoeg.

code:
1
Array ( [0] => [module:aanmelden_studenten] [1] => [2] => aanmelden_studenten )

Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
Niets gok ik :+

Probeer eens:

PHP:
1
2
3
4
5
<?
if (preg_match("/^(.*)\[module:(.*)\](.*)$/",  $row->content, $regs)) {
    print_r($regs);
 } 
?>


Die hoort t wel te doen AFAIK.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Thanks, maar op deze matcht hij helemaal niet :)

[ Voor 24% gewijzigd door Verwijderd op 17-01-2007 23:55 ]


Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
Oh... :X

Blijkt wel weer dat ik dr ab-so-luut geen held in ben :P

Acties:
  • 0 Henk 'm!

  • Tepel
  • Registratie: Juni 2006
  • Laatst online: 17-08-2024
PHP:
1
2
3
<?php
if (preg_match("/\[module:(.*?)\](.*)/", "[module:test] Retteketet", $regs)) { print_r($regs); }
?>

0x7F


Acties:
  • 0 Henk 'm!

  • EdwinG
  • Registratie: Oktober 2002
  • Laatst online: 12:47
Ik zou persoonlijk
code:
1
module:(.*)\]

Vervangen door:
code:
1
module:([^\]]*)\]

Om problemen te voorkomen met eventuele losse ']' verder in de tekst

Bezoek eens een willekeurige pagina


Acties:
  • 0 Henk 'm!

  • DataGhost
  • Registratie: Augustus 2003
  • Laatst online: 19-09 21:26

DataGhost

iPL dev

Verwijderd schreef op woensdag 17 januari 2007 @ 23:47:
Dag allen,

Ik ben een groot deel van de avond bezig met de volgende, behoorlijk eenvoudige regular expression voor Preg_match. Idee is dat ik een string uit de database in een array krijg en ik zo de volgorde kan wijzigen.

Als volgt.
PHP:
1
2
3
4
5
<?
if (preg_match("#(.*)\\[module:(.*)\\](.*)#",  $row->content, $regs)) {
    print_r($regs);
 } 
?>


Met als content: Hallo, dit is de module die uiteindelijk ge-include moet worden: [module:test] restje tekst

In mijn zoektoch op het internet kwam ik "Regular Expression Testscripts" tegen, hier kon ik de pattern en de tekst invullen, en alles werkte prima, en kreeg netjes drie subsets terug. Hoe kan het dat het in mijn php code PHP niet zo gaat?
In $regs[0] komt de volledige GEMATCHTE string te staan, dus [module:bladiebla]. Wat je nou probeert te doen is het volgende:
1. (.*) Match 0 of meer tekens en sla dit op
2. \\[module: Match '[module:'
3. (.*) Match 0 of meer tekens en sla dit op
4. \\] Match ']'
5. (.*) Match 0 of meer tekens en sla dit op

Bij 1 worden netjes 0 tekens gematcht, dit mag namelijk. Daarna wordt 2 gevonden, 3 ook (en die wordt opgeslagen, dat gebeurt ook netjes zoals je kan zien aan $regs[2]) en 4. Daarna komen weer 0 of meer tekens en dit matcht lekker weer 0. Volgens mij is preg_matchzijn PCRE's namelijk standaard nongreedy, in ieder geval aan het begin en eind. Voor de rest zijn ze standaard wel greedy, dus oppassen als onbekend is waar de rest van je string uit bestaat.
Ik zou persoonlijk iets doen als
PHP:
1
2
3
if (preg_match('#^(.*?)\[module:(.*?)\](.*)$#',  $row->content, $regs)) {
    print_r($regs);
 }

De ^ aan het begin en de $ aan het eind geven aan dat daartussen _DE HELE_ string gematcht moet zijn.
^ geeft het begin van de string aan. (.*?) matcht vervolgens zo min mogelijk tekens tot aan de eerste [module, vervolgens worden weer zo min mogelijk tekens gematcht tot aan de eerstvolgende ], zodat je niet in de knoei komt met een eventuele ] verderop (deze zal normaal, greedy, dan gematcht worden in plaats van de bedoelde). Hierna wordt gewoon greedy gematcht tot het eind van de string, dat maakt niet zoveel uit. Met $ wordt het einde van de string bedoeld, dus heb je alle tekst die je nodig hebt. Ook prefereer ik enkele quotes bij regular expressies.
Aangezien het me onwaarschijnlijk lijkt dat je [module:] in je tekst hebt of zelfs maar WILT matchen, raad ik je aan (.+?) in plaats van (.*?) te gebruiken na module:. Zo match je minstens 1 teken, anders lijkt het me vrij nutteloos.

Google ook even naar 'man perlre', daar staat een hoop nuttige informatie in. Verder vind ik 'The Regex Coach' wel een handig programma bij het snel inkloppen van regexen. Ik kan je trouwens ook nog aanraden eens te kijken naar preg_replace, aangezien je aangeeft dat je een volgorde wilt gaan wijzigen.

edit:
Paar foutjes hersteld, het is al laat.
En je had beter [perl] of [pcre] in je tag kunnen zetten, in plaats van [php]. Dit heeft namelijk, afgezien van de aanroep vanuit php, niks met php zelf te maken :)

[ Voor 11% gewijzigd door DataGhost op 18-01-2007 02:24 ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

DataGhost schreef op donderdag 18 januari 2007 @ 02:06:
[...]

De ^ aan het begin en de $ aan het eind geven aan dat daartussen _DE HELE_ string gematcht moet zijn.
Dat is helemaal niet nodig hoor. Ik zou gewoon dit doen:
PHP:
1
preg_match_all('/\[module:([^\]]*)\]/', $row->content, $matches);

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • DataGhost
  • Registratie: Augustus 2003
  • Laatst online: 19-09 21:26

DataGhost

iPL dev

crisp schreef op donderdag 18 januari 2007 @ 09:54:
[...]

Dat is helemaal niet nodig hoor. Ik zou gewoon dit doen:
PHP:
1
preg_match_all('/\[module:([^\]]*)\]/', $row->content, $matches);
Mja, de TS geeft eigenlijk aan dat hij begin en eind ook wil matchen om daarna iets met de volgorde te doen. Als dit niet nodig is had ik dat inderdaad ook weggelaten... Sterker nog, dan zou wat in de TS staat al 'werken'.
Pagina: 1