[Regex] Minimaal 1 uit 3 tokens, maar geen lege capture?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Zo heb je een maand geen regex vragen, en zo heb je er twee op een avond :)
In dit geval gaat het om regular expressions in .NET 2.0.

Ik zit met het volgende. Ik wil een opgegeven tijdspanne kunnen parsen van de vorm "(dagen)d(uren)h(minuten)", bijv. "12d6h33m" - dit is dan 12 dagen, 6 uur en 33 minuten.

Nu is het zo dat elk van de drie componenten (dagen, uren, minuten) optioneel is, maar dat er minimaal 1 van de 3 aanwezig moet zijn, en wanneer er meer dan 1 aanwezig zijn, dat ze wel in bovenstaande volgorde worden opgegeven. Dus "12d33m" en "6h" zijn beide geldig, maar "33m6h", "24h3h" en "" zijn niet geldig.

De regex die ik hiervoor bedacht heb is:
code:
1
(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?


Zoals je ziet bevat elk component een non-capturing group met resp. d, h of m erin, en daarbinnen een capturing group die alleen de decimalen captured. (in .NET wordt "(?: ... )" gebruikt om een non-capturing group aan te duiden).

Nu is het probleem dat bovenstaande regex ook de lege string matcht, omdat elk van de componenten optioneel is. Hoe krijg ik de regex nu zover dat hij minimaal 1 component wil zien?

Ik zou er een choice van kunnen maken: (a|b|c){1,3} maar dan vervalt de eis dat de componenten in de juiste volgorde gespecificeerd moeten worden...

Alvast bedankt!

Acties:
  • 0 Henk 'm!

  • Toolskyn
  • Registratie: Mei 2004
  • Laatst online: 22-06 11:01

Toolskyn

€ 500,-

Herhaal je regex gewoon drie keer met | ertussen, waarbij je dan in elk van de drie een van de componenten niet optioneel maakt. Misschien ziet het er niet heel elegant uit, maar korter kan het met een reguliere expressie niet.

gewooniets.nl


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Is niet elegant en bovendien ook slecht te onderhouden. Ipv stukken regex herhalen kan je imo nog beter gewoon in de code daarna checken of minstens 1 van de groepen gematched is. :)

Maar als het enige probleem is dat de lege string gematched wordt, kan je natuurlijk ook voor de eenvoudige oplossing gaan (KISS) en gewoon strlen(string) > 1 afdwingen. ;)

{signature}


Acties:
  • 0 Henk 'm!

  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Beiden bedankt :) Ik was er eigenlijk al een beetje bang voor dat hier geen nette oplossing voor was.

De reden dat ik mijn regex niet de lege string wilde laten capturen is dat ik nu vanuit code moet controleren of er 2 matchgroups zijn, en welke van de 2 niet de lege string heeft gecaptured. Deze bevat dan de capture groups die ik nodig heb.

Niet onoverkomelijk, maar ik hoopte dat het in de regex geregeld kon worden...

Acties:
  • 0 Henk 'm!

Verwijderd

MrBucket schreef op zondag 06 januari 2008 @ 11:45:

Niet onoverkomelijk, maar ik hoopte dat het in de regex geregeld kon worden...
Dat is de grootste fout die je kunt maken bij reguliere expressies. Alles ermee willen doen. Voor een lege string wil je sowieso een andere foutmelding hebben dan voor een malformed string, dus dat is al reden genoeg om vóór je regex te controleren of de string niet leeg is.

Regular expressions zijn er niet om te voorkomen dat je een regel code moet schrijven, ze zijn er om te voorkomen dat je er vele zal moeten schrijven.

Acties:
  • 0 Henk 'm!

  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Verwijderd schreef op zondag 06 januari 2008 @ 11:50:
[...]

Dat is de grootste fout die je kunt maken bij reguliere expressies. Alles ermee willen doen. Voor een lege string wil je sowieso een andere foutmelding hebben dan voor een malformed string, dus dat is al reden genoeg om vóór je regex te controleren of de string niet leeg is.
Ja, maar zelfs als mijn string een volledig geldige periode bevat, dan nog krijg ik 2 matches. Een expressie die een string van lengte 0 matcht zal nl. altijd gevonden worden.
Regular expressions zijn er niet om te voorkomen dat je een regel code moet schrijven, ze zijn er om te voorkomen dat je er vele zal moeten schrijven.
Sun Tsu? :P

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
MrBucket schreef op zondag 06 januari 2008 @ 11:54:
[...]
Ja, maar zelfs als mijn string een volledig geldige periode bevat, dan nog krijg ik 2 matches. Een expressie die een string van lengte 0 matcht zal nl. altijd gevonden worden.
Dat staat er los van. Je moet gewoon eerst een lengtecheck willen doen, al was het inderdaad maar om betere feedback te kunnen geven. :)

En als je begin en einde string operators toevoegd aan je regex lijkt het me dat je nooit meer dan 1 match krijgt. ;)
Sun Tsu? :P
Het is iig een wijze opmerking die wel vaker over regular expressions gemaakt wordt. Een regex kunnen gebruiken is heel handig, maar vergeet gewoon de meest basale string functies (strlen, strpos en strstr) niet. :)

[ Voor 12% gewijzigd door Voutloos op 06-01-2008 12:22 ]

{signature}

Pagina: 1