Ricerca…


Gruppi di acquisizione di base

Un gruppo è una sezione di un'espressione regolare racchiusa tra parentesi () . Questo è comunemente chiamato "sottoespressione" e ha due scopi:

  • Rende atomica la sottoespressione, cioè corrisponderà, fallirà o ripeterà nel suo complesso.
  • La porzione di testo che corrisponde è accessibile nel resto dell'espressione e nel resto del programma.

I gruppi sono numerati nei motori regex, a partire da 1. Tradizionalmente, il numero massimo di gruppi è 9, ma molti aromi regex moderni supportano un numero maggiore di gruppi. Il gruppo 0 corrisponde sempre all'intero pattern, allo stesso modo in cui circolerebbe l'intera regex con parentesi.

Il numero ordinale aumenta con ciascuna parentesi di apertura, indipendentemente dal fatto che i gruppi siano posizionati uno dopo l'altro o nidificati:

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

gruppi e loro numeri

Dopo che un'espressione raggiunge una corrispondenza generale, tutti i suoi gruppi saranno in uso, indipendentemente dal fatto che un particolare gruppo sia riuscito a combinare qualcosa.

Un gruppo può essere facoltativo, come (baz)? sopra, o in una parte alternativa dell'espressione che non è stata utilizzata per la corrispondenza, come (bla) sopra. In questi casi, i gruppi non corrispondenti semplicemente non conterranno alcuna informazione.

Se un quantificatore viene posizionato dietro un gruppo, come in (qux)+ sopra, il numero complessivo di gruppi dell'espressione rimane lo stesso. Se un gruppo corrisponde a più di una volta, il suo contenuto sarà l'ultima occorrenza della partita. Tuttavia, i sapori regex moderni consentono di accedere a tutte le occorrenze di sub-match.


Se si desidera recuperare la data e il livello di errore di una voce del registro come questa:

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

Potresti usare qualcosa come questo:

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

Ciò estrarrebbe la data della voce di registro 2012-06-06 come gruppo di acquisizione 1 e il livello di errore ERROR come gruppo di acquisizione 2.

Backreferences e gruppi non di cattura

Poiché i gruppi sono "numerati", alcuni motori supportano anche la corrispondenza di ciò che un gruppo ha precedentemente abbinato di nuovo.

Supponendo che tu voglia abbinare qualcosa dove due stringhe uguali di lunghezza tre sono divise da un $ che useresti:

(.{3})\$\1

Questo corrisponderebbe a qualsiasi delle seguenti stringhe:

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

Se vuoi che un gruppo non sia numerato dal motore, puoi dichiararlo non catturante. Un gruppo non catturante assomiglia a questo:

(?:)

Sono particolarmente utili per ripetere un determinato pattern un numero qualsiasi di volte, poiché un gruppo può anche essere usato come un "atomo". Tenere conto:

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

Ciò corrisponderà a due voci di registrazione nelle righe adiacenti che hanno lo stesso timestamp e la stessa voce.

Gruppi di cattura con nome

Alcuni sapori di espressioni regolari consentono gruppi di cattura denominati . Invece di un indice numerico è possibile fare riferimento a questi gruppi per nome nel codice successivo, cioè in backreferences, nel pattern replace e nelle righe seguenti del programma.

Gli indici numerici cambiano man mano che il numero o la disposizione dei gruppi in un'espressione cambia, quindi sono più fragili in confronto.

Ad esempio, per abbinare una parola ( \w+ ) racchiusa tra virgolette singole o doppie ( ['"] ), potremmo usare:

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

Che è equivalente a:

(['"])\w+\1

In una situazione semplice come questa, un gruppo di cattura regolare e numerato non ha alcuno svantaggio.

In situazioni più complesse l'uso di gruppi nominati renderà la struttura dell'espressione più evidente al lettore, il che migliora la manutenibilità.

L'analisi dei file di log è un esempio di una situazione più complessa che beneficia dei nomi dei gruppi. Questo è l' 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

La seguente espressione cattura le parti in gruppi denominati:

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

La sintassi dipende dal sapore, quelli comuni sono:

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

backreference:

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

Nell'esperienza .NET è possibile avere diversi gruppi che condividono lo stesso nome, che utilizzeranno gli stack di acquisizione .

In PCRE devi abilitarlo esplicitamente usando il modificatore (?J) ( PCRE_DUPNAMES ) o usando il gruppo di reset delle diramazioni (?|) . Tuttavia, solo l'ultimo valore catturato sarà accessibile.

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


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow