Cookies op Tweakers

Tweakers maakt gebruik van cookies, onder andere om de website te analyseren, het gebruiksgemak te vergroten en advertenties te tonen. Door gebruik te maken van deze website, of door op 'Ga verder' te klikken, geef je toestemming voor het gebruik van cookies. Wil je meer informatie over cookies en hoe ze worden gebruikt, bekijk dan ons cookiebeleid.

Meer informatie
sluiten

Laatste kans om te stemmen voor de Tweakers Awards 2019/2020!

Dit jaar organiseert Tweakers alweer voor de dertiende keer de Tweakers Awards, de publieksprijs voor de beste technologie- en elektronicaproducten. Laat je stem gelden en maak kans op een Google Stadia Premiere Edition, Nintendo Switch inclusief Mario Kart of een setje Sony WF-1000XM3 in-ear oordoppen.

Stemmen

Toon posts:

Softwareontwikkeling FAQ - Regular expressions

Pagina: 1
Acties:
  • 606 views sinds 30-01-2008

Onderwerpen


  • NMe
  • Registratie: februari 2004
  • Laatst online: 17-01 20:09

NMe

Quia Ego Sic Dico.

Topicstarter
Mede-auteurs:
  • tomato
  • Registratie: november 1999
  • Niet online

tomato

  • Arien
  • Registratie: september 2000
  • Laatst online: 15-05-2008

Arien

  • Grum
  • Registratie: juni 2001
  • Niet online

Grum

Softwareontwikkeling FAQ: Regular expressions

Met dank aan Arien, tomato en Grum. :)
Inhoudsopgave
« · ^

Links
« · ^

Boeken
  • Mastering Regular Expressions, Second Edition


    Door: Jeffrey Friedl

    ISBN: 0596002890

    O'Reilly & Associates Inc.
« · ^

Wat zijn reguliere expressies?
Reguliere expressies zijn een manier om een (abstracte) taal te omschrijven. Je kunt zo aangeven welke woorden syntactisch correct zijn (en dus ook welke woorden dat niet zijn). Is het eerste dat in je opkomt nu ":?", vergeet dit dan. De onderstaande omschrijving voldoet prima.

Reguliere expressies zijn een manier om strings te omschrijven. Hoe je een bepaalde regex schrijft hangt af van de taal of tool die je gebruikt, kijk dus in de docs. Ik gebruik in het vervolg Perl als voorbeeld.

Voorbeeld
Laten we eenvoudig beginnen en eerst een kijken hoe zo'n regex er dan in het wild uitziet.

Stel, je wilt uit een bestand (waarin op elke regel een woord staat) de woorden halen waar een "a" in zit. Een stukje van de code zou zo kunnen zijn in Perl:

Perl:
1
2
3
while (<FILE>) {   # lees woord in
    print if /a/;  # print als er een "a" in zit
}


Wat er hier gebeurt is dat iedere keer een regel uit het bestand gelezen wordt (en de inhoud van die regel automagisch in de variabele $_ gekopieerd wordt). Vervolgens wordt gekeken of de regel (dat wil zeggen de waarde van de magische $_ variabele) voldoet aan de regex /a/, en als dat zo is wordt de regel (dat wil zeggen de waarde van de magische $_ variabele, die zo magisch is dat je hem niet eens ziet) geprint.

Zoals je ziet matcht de "a" in de regex /a/ zichzelf. Dit geldt voor de meeste tekens.
Hoe zou je kunnen kijken welke woorden "aa" (dus een "a" gevolgd door nog een "a") bevatten? Denk eerst even na...

Inderdaad, met de regex /aa/. Het achter elkaar zetten van tekens in een regex heeft tot gevolg dat de tekens in volgorde gematcht moeten worden.

Nou zei ik boven dat de meeste tekens zichzelf matchen, maar wat doen die andere tekens dan? Die andere tekens (metacharacters) zorgen ervoor dat er iets speciaals gebeurt, ze geven bijvoorbeeld een keuze of een herhaling aan.

Als een teken speciaal is kun je het zo speciaal maken dat het weer normaal wordt (dus: zichzelf matcht) door er een backslash voor te zetten. Op dezelfde manier kun je een normaal teken speciaal maken (zie hieronder).

Keuzes
Wat nu als je wilt kijken of een regel "aa" of "ee" bevat? Voor keuzes kun je het pipe symbool op de volgende manier gebruiken:

Perl:
1
2
/aa|ee/  # match "aa" OF "ee" in een string
/aa\|ee/ # match "aa|ee" (letterlijk!) in een string



Herhaling
Om aan te geven dat een bepaald teken een aantal keer herhaald moet/mag worden kun je de volgende constructies gebruiken:

Perl:
1
2
3
4
5
6
7
8
9
/a*/    # match 0 of meer keer "a"
/a+/    # match 1 of meer keer "a"
/a{1,2} # match 1 of twee keer "a"
/a{1,}  # match 1 of meer keer "a"
/a{2}/  # match precies 2 keer "a"
/a*/ # matcht 0 of meer keer "a" (bijv: '', 'a', 'aaaaaaa')
/a+/ # matcht 1 of meer keer "a" (bijv: 'a', 'aaaaa')
/a{3,5} # matcht drie tot vijf keer "a" (bijv: 'aaaa')
/a{2,} # matcht twee of meer keer "a" (bijv: 'aaaaa')


Uit zichzelf zal de regex engine proberen zo vaak mogelijk te matchen als het de keuze krijgt tussen minder of meer matchen op dezelfde plek. Dus (match in vierkante haken):

Perl:
1
/a+/  # matcht b[aaa]bbaaaaaa


Je ziet dat /a+/ zo vaak mogelijk een "a" match. Of is dat niet zo? Verder naar recht staan meer"a"s dan hij er nu pakt! :o

Het belangrijke punt om te onthouden is dat een regex van links naar rechts werkt en houdt van "instant gratification" (als hij nu kan zorgen voor een complete match, waarom dan nog verder gaan? maar ook: als hij nu veel kan pakken in plaats van weinig, waarom dan met weinig tevreden zijn?). Lees het stukje hierboven nog eens en let op het vetgedrukte "op dezelfde plek".

Grouping
Om stukken van een regex te groeperen gebruik je haakjes, bijvoorbeeld:

Perl:
1
2
3
4
5
/aa|bb/    # matcht "aa" of "bb"
/a(a|b)b/  # matcht "aab" of "abb"
/ab{2}/    # matcht "abb"
/(ab){2}/  # matcht "abab"
/ab?a/   # matcht 'aa' en 'aba'



Assertions
Soms wil je niet een bepaald teken matchen, maar wil je alleen kijken of iets waar is of niet.

Om aan te geven waar je wilt dat de match moet zijn kan je anchors gebruiken:

Perl:
1
2
/^a/  # begint met a
/a$/  # eindigt met a


De ^ zorgt er dus voor dat de match alleen slaagt als ^ kan matchen aan het begin van de string. ^ neemt geen ruimte in! (Idem voor $).

Ook kan je kijken of je op de grens van een "woord" bent (een "woord" bestaat in Perl uit letters, cijfer en de underscore, tenzij je met Unicode bezig bent) of juist niet:

Perl:
1
2
3
4
/\ber\b/  # "er" als los woord
/\Ber\b/  # "er" aan het einde van een woord
/\ber\b/ # "er" als los woord (bijv: "Het gaat er goed")
/\Ber\b/ # "er" aan het einde van een woord (bijv: "Achter de molen")



Character classes
Als kortere notatie voor keuzes tussen karakters kun je character classes gebruiken. Bijvoorbeeld om een teken te matchen dat een "a", een "b" of een "c" kan zijn kan beide onderstaande constructies gebruiken:

Perl:
1
2
3
/a|b|c/  # alternatie: de normale "keuze"
/[abc]/  # character class van letters "a", "b" en "c"
/[a-c]/  # idem van de range van "a" tot en met "c"


Een character class is een opsomming van tekens, en binnen de character class (dus tussen de begin [ en de eind ] verliezen metacharacters als |, (, ), en . (waar ik het zo over heb) hun speciale betekenis.

Perl:
1
/[|(){}]/  # match het pipe symbool of een van de haken


Om binnen een character class een "-" te gebruiken kan je hem aan het begin (direct na de openingshaak), aan het einde van de class zetten of escapen:

Perl:
1
2
3
/[ac-z-]/  # match een kleine letter behalve b, of de min
/[-ac-z]/  # idem
/[a\-c-z]/ # idem


Kijk eens of je in de docs van jouw taal of tool kunt vinden hoe je een letterlijke "[" of "]" in een character class op kunt nemen.

NMe wijzigde deze reactie 21-12-2019 18:16 (32%)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Dit topic is gesloten.



Apple iPhone 11 Microsoft Xbox Series X LG OLED C9 Google Pixel 4 CES 2020 Samsung Galaxy S20 Sony PlayStation 5 Nintendo Switch Lite

'14 '15 '16 '17 2018

Tweakers vormt samen met Hardware Info, AutoTrack, Gaspedaal.nl, Nationale Vacaturebank, Intermediair en Independer DPG Online Services B.V.
Alle rechten voorbehouden © 1998 - 2020 Hosting door True