Regular Expressions
Groepen vastleggen
Zoeken…
Basic Capture Groups
Een groep is een gedeelte van een reguliere expressie tussen haakjes ()
. Dit wordt meestal "sub-expressie" genoemd en dient twee doelen:
- Het maakt de subexpressie atomisch, dat wil zeggen dat het ofwel overeenkomt, faalt of als geheel herhaalt.
- Het gedeelte van de overeenkomende tekst is toegankelijk in de rest van de expressie en de rest van het programma.
Groepen zijn genummerd in regex-motoren, beginnend met 1. Traditioneel is het maximale groepsnummer 9, maar veel moderne regex-smaken ondersteunen hogere groepstellingen. Groep 0 komt altijd overeen met het hele patroon, op dezelfde manier als de hele regex met haakjes wordt omgeven.
Het rangtelwoord neemt toe met elke opening tussen haakjes, ongeacht of de groepen achter elkaar worden geplaatst of genest:
foo(bar(baz)?) (qux)+|(bla)
1 2 3 4
groepen en hun nummers
Nadat een expressie een algehele overeenkomst heeft bereikt, zijn alle groepen in gebruik - of een bepaalde groep erin is geslaagd om iets te matchen of niet.
Een groep kan optioneel zijn, zoals (baz)?
hierboven, of in een alternatief deel van de uitdrukking dat niet werd gebruikt voor de wedstrijd, zoals (bla)
hierboven. In deze gevallen bevatten niet-overeenkomende groepen eenvoudigweg geen informatie.
Als een kwantificeerder achter een groep wordt geplaatst, zoals in (qux)+
hierboven, blijft het totale aantal groepen van de uitdrukking hetzelfde. Als een groep meer dan één keer overeenkomt, is de inhoud ervan het laatste exemplaar dat voorkomt. Moderne regex-smaken geven echter toegang tot alle sub-match-voorvallen.
Als u de datum en het foutniveau van een logboekitem zoals deze wilt ophalen:
2012-06-06 12:12.014 ERROR: Failed to connect to remote end
Je zou zoiets als dit kunnen gebruiken:
^(\d{4}-\d{2}-\d{2}) \d{2}:\d{2}.\d{3} (\w*): .*$
Dit zou de datum van de logboekvermelding 2012-06-06
als capture-groep 1 en het foutniveau ERROR
als capture-groep 2 extraheren.
Backreferences en niet-vastleggende groepen
Aangezien groepen "genummerd" zijn, ondersteunen sommige zoekmachines ook het matchen van wat een groep eerder opnieuw heeft gematcht.
Ervan uitgaande dat je iets wilde matchen waarbij twee gelijk aan strings van lengte drie worden gedeeld door een $
je zou gebruiken:
(.{3})\$\1
Dit komt overeen met een van de volgende strings:
"abc$abc"
"a b$a b"
"af $af "
" $ "
Als u wilt dat een groep niet door de motor wordt genummerd, kunt u deze niet-vastleggen. Een niet-vastleggende groep ziet er zo uit:
(?:)
Ze zijn bijzonder nuttig om een bepaald patroon een aantal keren te herhalen, omdat een groep ook als een "atoom" kan worden gebruikt. Overwegen:
(\d{4}(?:-\d{2}){2} \d{2}:\d{2}.\d{3}) (.*)[\r\n]+\1 \2
Dit komt overeen met twee logboekvermeldingen in de aangrenzende regels met dezelfde tijdstempel en dezelfde vermelding.
Benoemde Capture Groups
Sommige reguliere expressiesmaken laten benoemde vastleggroepen toe . In plaats van door een numerieke index kunt u naar deze groepen op naam verwijzen in de volgende code, dat wil zeggen in backreferences, in het vervangpatroon en in de volgende regels van het programma.
Numerieke indexen veranderen naarmate het aantal of de rangschikking van groepen in een uitdrukking verandert, zodat ze in vergelijking brozer zijn.
Om bijvoorbeeld een woord ( \w+
) te vinden dat tussen enkele of dubbele aanhalingstekens ( ['"]
) staat, kunnen we het volgende gebruiken:
(?<quote>['"])\w+\k{quote}
Dat is gelijk aan:
(['"])\w+\1
In een eenvoudige situatie als deze heeft een normale, genummerde groep geen nadelen.
In meer complexe situaties zal het gebruik van benoemde groepen de structuur van de uitdrukking duidelijker maken voor de lezer, wat de onderhoudbaarheid verbetert.
Het parseren van logbestanden is een voorbeeld van een complexere situatie die baat heeft bij groepsnamen. Dit is het Apache Common Log Format (CLF):
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
Met de volgende expressie worden de delen in benoemde groepen vastgelegd:
(?<ip>\S+) (?<logname>\S+) (?<user>\S+) (?<time>\[[^]]+\]) (?<request>"[^"]+") (?<status>\S+) (?<bytes>\S+)
De syntaxis is afhankelijk van de smaak, veel voorkomende zijn:
-
(?<name>...)
-
(?'name'...)
-
(?P<name>...)
terugverwijzingen:
-
\k<name>
-
\k{name}
-
\k'name'
-
\g{name}
-
(?P=name)
In de .NET-smaak kunt u verschillende groepen met dezelfde naam hebben, ze gebruiken capture-stacks .
In PCRE moet u dit expliciet inschakelen met behulp van de (?J)
PCRE_DUPNAMES
( PCRE_DUPNAMES
), of met behulp van de tak- PCRE_DUPNAMES
(?|)
. Alleen de laatst vastgelegde waarde is echter toegankelijk.
(?J)(?<a>...)(?<a>...)
(?|(?<a>...)|(?<a>...))