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
]