Sök…


Grundläggande fångstgrupper

En grupp är en del av ett reguljärt uttryck som är inneslutet inom parentes () . Detta kallas vanligtvis "underuttryck" och tjänar två syften:

  • Det gör att underuttrycket blir atomiskt, dvs att det antingen kommer att matcha, misslyckas eller upprepa som en helhet.
  • Den del av texten som den matchade är tillgänglig i resten av uttrycket och resten av programmet.

Grupper är numrerade i regex-motorer, börjar med 1. Traditionellt är det maximala gruppnumret 9, men många moderna regex-smaker stöder högre gruppantal. Grupp 0 matchar alltid hela mönstret, på samma sätt som hela regexet med parenteser skulle göra.

Ordinalantalet ökar med varje öppningsparentes, oavsett om grupperna placeras efter varandra eller kapslade:

foo(bar(baz)?) (qux)+|(bla)
   1   2       3      4

grupper och deras antal

När ett uttryck har uppnått en övergripande match kommer alla dess grupper att användas - oavsett om en viss grupp har lyckats matcha något eller inte.

En grupp kan vara valfri, som (baz)? ovan, eller i en alternativ del av uttrycket som inte användes i matchen, som (bla) ovan. I dessa fall innehåller grupper som inte matchar helt enkelt ingen information.

Om en kvantifierare placeras bakom en grupp, som i (qux)+ ovan, (qux)+ det totala gruppantalet för uttrycket detsamma. Om en grupp matchar mer än en gång kommer innehållet att vara den sista matchningen. Moderna regex-smaker tillåter dock åtkomst till alla sub-match-händelser.


Om du vill hämta datum och felnivå för en loggpost som den här:

2012-06-06 12:12.014 ERROR: Failed to connect to remote end

Du kan använda något liknande:

^(\d{4}-\d{2}-\d{2}) \d{2}:\d{2}.\d{3} (\w*): .*$

Detta skulle extrahera datumet för loggposten 2012-06-06 som capture group 1 och felnivån ERROR som capture group 2.

Återreferenser och icke-fångargrupper

Eftersom grupper är "numrerade" stöder vissa motorer också matchning av vad en grupp tidigare har matchat igen.

Antagande att du ville matcha något där två lika strängar med längd tre är uppdelade med en $ du skulle använda:

(.{3})\$\1

Detta skulle matcha någon av följande strängar:

"abc$abc"
"a b$a b"
"af $af "
"   $   "

Om du vill att en grupp inte ska numreras av motorn kan du förklara att den inte fångas. En grupp som inte fångar ser ut så här:

(?:)

De är särskilt användbara för att upprepa ett visst mönster valfritt antal gånger, eftersom en grupp också kan användas som en "atom". Överväga:

(\d{4}(?:-\d{2}){2} \d{2}:\d{2}.\d{3}) (.*)[\r\n]+\1 \2

Detta kommer att matcha två loggposter i de angränsande linjerna som har samma tidsstämpel och samma post.

Namngivna fångstgrupper

Vissa vanliga uttryckssmaker tillåter namngivna fångstgrupper . Istället för med ett numeriskt index kan du hänvisa till dessa grupper med namn i efterföljande kod, dvs i bakreferenser, i ersättningsmönstret och i följande rader i programmet.

Numeriska index ändras när antalet eller arrangemanget av grupper i ett uttryck förändras, så de är mer spröda i jämförelse.

Till exempel för att matcha ett ord ( \w+ ) som är bifogat antingen enstaka eller dubbla citat ( ['"] ), kan vi använda:

(?<quote>['"])\w+\k{quote}

Vilket motsvarar:

(['"])\w+\1

I en enkel situation som denna har en vanlig, numrerad fångargrupp inga nackdelar.

I mer komplexa situationer kommer användningen av namngivna grupper att göra uttryckets struktur tydligare för läsaren, vilket förbättrar underhållsförmågan.

Analys av loggfil är ett exempel på en mer komplex situation som gynnas av gruppnamn. Detta är 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

Följande uttryck fångar upp delarna i namngivna grupper:

(?<ip>\S+) (?<logname>\S+) (?<user>\S+) (?<time>\[[^]]+\]) (?<request>"[^"]+") (?<status>\S+) (?<bytes>\S+)

Syntaxen beror på smaken, vanliga är:

  • (?<name>...)
  • (?'name'...)
  • (?P<name>...)

bakåtreferenser:

  • \k<name>
  • \k{name}
  • \k'name'
  • \g{name}
  • (?P=name)

I .NET-smaken kan du ha flera grupper som delar samma namn, de kommer att använda fångstbuntar .

I PCRE måste du aktivera det uttryckligen med (?J) modifieraren ( PCRE_DUPNAMES ), eller genom att använda återställningsgruppen för gren (?|) . Endast det senast fångade värdet kommer att vara tillgängligt.

(?J)(?<a>...)(?<a>...)
(?|(?<a>...)|(?<a>...))


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow