[php] regex netter maken

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • verytallman
  • Registratie: Augustus 2001
  • Laatst online: 18-08 18:12
Ik heb een volgende string:

1(2|3)

oftewel: cijfer(cijfer|cijfer), waarbij het cijfer geen limiet heeft.

Deze 3 cijfers wil ik eruit halen, nu heb ik de volgende code:

PHP:
1
2
3
preg_match("/[0-9]{1,}/", $string, $cijfer1);
preg_match("/\([0-9]{1,}\|/", $string, $cijfer2);
preg_match("/\|[0-9]{1,}\)/", $string, $cijfer3);


Wat me de volgende output geeft:
$cijfer1 = 1
$cijfer2 = (2|
$cijfer3 = |3)

Nu wil ik die ( en | tekens weg hebben bij $cijfer2 en $cijfer3.

Nu haal ik ze er nog later af met wat extra code, maar ik wel eigenlijk dat me regex het meteen goed doet.

Acties:
  • 0 Henk 'm!

  • Arjan
  • Registratie: Juni 2001
  • Niet online

Arjan

copyright is wrong

ik ben niet bekend met php, maar ik verwacht dat je de mogelijkheid hebt om backreferences te gebruiken?

PHP:
1
preg_match("/\(([0-9]{1,})\|/", $string, $cijfer2);


in dit geval zou je eerste backreference naar het getal alleen wijzen bij de meeste talen is die op te halen met $1
hoe je die ophaald bij php zul je even zelf achteraan moeten :)

oprecht vertrouwen wordt nooit geschaad


Acties:
  • 0 Henk 'm!

  • robbert
  • Registratie: April 2002
  • Laatst online: 11:40
PHP:
1
preg_match("/(\d*)\((\d*)\|(\d*)\)/", $string, $matches);

Zoiets :?

Acties:
  • 0 Henk 'm!

  • KappuhH
  • Registratie: Augustus 2004
  • Niet online
PHP:
1
2
3
4
5
6
<?php
echo $string;
str_replace("(", " ", $string);
str_replace("|", " ", $string);
str_replace(")", " ", $string);
$getallen = spliti(" ", $string);


Getallen[0] gevat nu het eerste getal, getallen[1] het tweede en getallen[2] het derde. Maar of dit echt een vooruitgang is weet ik niet.

Acties:
  • 0 Henk 'm!

  • robbert
  • Registratie: April 2002
  • Laatst online: 11:40
KappuhH schreef op woensdag 10 januari 2007 @ 23:35:
PHP:
1
2
3
4
5
6
<?php
echo $string;
str_replace("(", " ", $string);
str_replace("|", " ", $string);
str_replace(")", " ", $string);
$getallen = spliti(" ", $string);


Getallen[0] gevat nu het eerste getal, getallen[1] het tweede en getallen[2] het derde. Maar of dit echt een vooruitgang is weet ik niet.
Dat kan natuurlijk allemaal in 1 regel :)
PHP:
1
$getallen = split(" ", str_replace(array("(", "|", ")"), " ", $string))

Qua vooruitgang, ik neem aan dat die regex (van mij) wel iets sneller zal zijn. Maar of je dat nou echt zal merken als dit 1 zielige keer moet doen.

Gezien ik geen zak te doen heb, maar even een testje gedaan:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$tijd = microtime(true);
for($i = 0; $i < 1000000; $i++) {
    $matches = array();
    preg_match("/(\d*)\((\d*)\|(\d*)\)/", "4(1|3)", $matches);
}
printf("Tijd regex: %f<br />", microtime(true)-$tijd);

$tijd = microtime(true);
for($i = 0; $i < 1000000; $i++) {
    $getallen = split(" ", str_replace(array("(", "|", ")"), " ", "4(1|3)"));
}
printf("Tijd split: %f<br />", microtime(true)-$tijd);

$tijd = microtime(true);
for($i = 0; $i < 1000000; $i++) {
    $string = str_replace("(", " ", "4(1|3)");
    $string = str_replace("|", " ", $string);
    $string = str_replace(")", " ", $string);
    $getallen = spliti(" ", $string);
}
printf("Tijd KappuhH split: %f<br />", microtime(true)-$tijd);


Wat het volgende resultaat gaf:
code:
1
2
3
Tijd regex: 3.682290
Tijd split: 5.370418
Tijd KappuhH split: 6.234539

Mijn regex methode is dus inderdaad sneller :P

Dat jou split slomer is dan die van mij is ook logisch, al die replaces kan ik bij mij in 1 keer doen (hoeft dus maar 1 keer de hele string door te lopen ipv 3 keer). En hij hoeft niet telkens geheugen voor een nieuwe string te alloceren.

[ Voor 58% gewijzigd door robbert op 10-01-2007 23:53 ]


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

KappuhH schreef op woensdag 10 januari 2007 @ 23:35:
PHP:
1
2
3
4
5
6
<?php
echo $string;
str_replace("(", " ", $string);
str_replace("|", " ", $string);
str_replace(")", " ", $string);
$getallen = spliti(" ", $string);


Getallen[0] gevat nu het eerste getal, getallen[1] het tweede en getallen[2] het derde. Maar of dit echt een vooruitgang is weet ik niet.
Dit is natuurlijk niet de bedoeling he? Je checked niet op een bepaald patroon, i.e. bij jou zou de volgende string ook gesplit worden, ook al klopt het patroon niet: "(asda(asdasd)".
Wil je nu beweren dat er in $getallen ook daadwerkelijk zich getallen bevinden? :P
robbert schreef op woensdag 10 januari 2007 @ 23:25:
PHP:
1
preg_match("/(\d*)\((\d*)\|(\d*)\)/", $string, $matches);

Zoiets :?
Ik weet niet precies wat de TS bedoelt met dat cijfer geen limiet heeft, maar het lijkt me dat cijfer minstens 1 keer moet voorkomen. Als dat het geval is dan volstaat je regexp niet, aangezien je de characterclass d (decimaal) voorzien hebt van een quantificator die een decimaal '0 of meer' accepteert. De volgende string zou dan ook matchen bij jou: "(|)". Dat lijkt me niet de bedoeling, maar ik kan het ook verkeerd begrepen hebben.
Ik zou zeggen:
PHP:
1
preg_match("/(\d+)\((\d+)\|(\d+)\)/", $string, $matches);

Verder zou ik de TS aanraden om zich te verdiepen in formele talen en een PCRE reference.

Acties:
  • 0 Henk 'm!

  • sam.vimes
  • Registratie: Januari 2007
  • Laatst online: 08-06 08:44
verytallman schreef op woensdag 10 januari 2007 @ 23:20:
Ik heb een volgende string:

1(2|3)

oftewel: cijfer(cijfer|cijfer), waarbij het cijfer geen limiet heeft.

Deze 3 cijfers wil ik eruit halen, nu heb ik de volgende code:

PHP:
1
2
3
preg_match("/[0-9]{1,}/", $string, $cijfer1);
preg_match("/\([0-9]{1,}\|/", $string, $cijfer2);
preg_match("/\|[0-9]{1,}\)/", $string, $cijfer3);
De term "waarbij het cijfer geen limiet heeft" is een beetje onduidelijk, maar uit het feit dat er een match op 1 of meer cijfers wordt uitgevoerd
code:
1
{1,}
begrijp ik dat er geen cijfers maar (gehele) getallen worden bedoeld. De string kan dus ook de volgende vorm hebben: 123(45|6789).

Oplossing is afhankelijk van wat er verder nog in de string staat.

Als er nog rommel omheen staat ($string = "1 ervoor 123(45|6789) 2 erachter") zul je met preg_match() moeten werken:
PHP:
1
preg_match("/(\d+)\((\d+)\|(\d+)\)/", $getallen);

waarna $getallen[1], [2] en [3] de submatches 123, 45 en 6789 bevatten ($getallen[0] bevat de volledige match "123(45|6789)" ).

Als dit alles is wat er in de string staat ($string = "123(45|6789)"), is preg_split() waarschijnlijk het simpelst en snelst:
PHP:
1
$getallen = preg_split("/\D+/", $string);

waarna $getallen[0], [1] en [2] de getallen 123, 45 en 6789 zullen bevatten.


Hope this helps...

Acties:
  • 0 Henk 'm!

  • robbert
  • Registratie: April 2002
  • Laatst online: 11:40
prototype schreef op donderdag 11 januari 2007 @ 06:22:
Ik zou zeggen:
PHP:
1
preg_match("/(\d+)\((\d+)\|(\d+)\)/", $string, $matches);
Je hebt gelijk ;) Foutje van mij.
Pagina: 1