Frage Was ist eine nicht einfangende Gruppe? Was macht (? :)?


Wie ?: wird benutzt und wofür ist es gut?


1320
2017-08-18 13:17


Ursprung


Antworten:


Lassen Sie mich versuchen, dies mit einem Beispiel zu erklären.

Betrachten Sie den folgenden Text:

https://stackoverflow.com/
https://stackoverflow.com/questions/tagged/regex

Jetzt, wenn ich den Regex unten über ihn anwende ...

(https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?

... würde ich folgendes Ergebnis erhalten:

Match "https://stackoverflow.com/"
     Group 1: "http"
     Group 2: "stackoverflow.com"
     Group 3: "/"

Match "https://stackoverflow.com/questions/tagged/regex"
     Group 1: "http"
     Group 2: "stackoverflow.com"
     Group 3: "/questions/tagged/regex"

Aber das Protokoll interessiert mich nicht - ich möchte nur den Host und den Pfad der URL. Also ändere ich die Regex, um die nicht einfangende Gruppe aufzunehmen (?:).

(?:https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?

Nun sieht mein Ergebnis so aus:

Match "https://stackoverflow.com/"
     Group 1: "stackoverflow.com"
     Group 2: "/"

Match "https://stackoverflow.com/questions/tagged/regex"
     Group 1: "stackoverflow.com"
     Group 2: "/questions/tagged/regex"

Sehen? Die erste Gruppe wurde nicht erfasst. Der Parser verwendet ihn, um den Text zu vergleichen, ignoriert ihn jedoch später im Endergebnis.


BEARBEITEN:

Wie gewünscht, lass mich versuchen, auch Gruppen zu erklären.

Nun, Gruppen dienen vielen Zwecken. Sie können Ihnen helfen, genaue Informationen aus einer größeren Übereinstimmung (die auch benannt werden kann) zu extrahieren, sie lassen Sie eine vorherige übereinstimmende Gruppe rückmelden und können für Ersetzungen verwendet werden. Lass uns ein paar Beispiele ausprobieren, sollen wir?

Ok, stellen Sie sich vor, Sie haben eine Art von XML oder HTML (seien Sie sich dessen bewusst Regex ist möglicherweise nicht das beste Werkzeug für den Job, aber es ist schön, als ein Beispiel). Sie möchten die Tags analysieren, damit Sie so etwas tun können (ich habe Leerzeichen hinzugefügt, um das Verständnis zu erleichtern):

   \<(?<TAG>.+?)\> [^<]*? \</\k<TAG>\>
or
   \<(.+?)\> [^<]*? \</\1\>

Die erste Regex hat eine benannte Gruppe (TAG), während die zweite eine gemeinsame Gruppe verwendet. Beide Regexes machen dasselbe: Sie verwenden den Wert aus der ersten Gruppe (den Namen des Tags), um das schließende Tag zu finden. Der Unterschied besteht darin, dass der erste Name den Wert verwendet und der zweite den Gruppenindex (der bei 1 beginnt).

Lassen Sie uns jetzt einige Ersetzungen versuchen. Betrachten Sie den folgenden Text:

Lorem ipsum dolor sit amet consectetuer feugiat fames malesuada pretium egestas.

Lasst uns den dummen Regex darüber benutzen:

\b(\S)(\S)(\S)(\S*)\b

Diese Regex stimmt Wörter mit mindestens 3 Zeichen überein und verwendet Gruppen, um die ersten drei Buchstaben zu trennen. Das Ergebnis ist folgendes:

Match "Lorem"
     Group 1: "L"
     Group 2: "o"
     Group 3: "r"
     Group 4: "em"
Match "ipsum"
     Group 1: "i"
     Group 2: "p"
     Group 3: "s"
     Group 4: "um"
...

Match "consectetuer"
     Group 1: "c"
     Group 2: "o"
     Group 3: "n"
     Group 4: "sectetuer"
...

Also, wenn wir den Substitutions-String anwenden ...

$1_$3$2_$4

... darüber versuchen wir, die erste Gruppe zu verwenden, fügen einen Unterstrich hinzu, verwenden die dritte Gruppe, dann die zweite Gruppe, fügen einen weiteren Unterstrich und dann die vierte Gruppe hinzu. Die resultierende Zeichenfolge wäre wie die folgende.

L_ro_em i_sp_um d_lo_or s_ti_ a_em_t c_no_sectetuer f_ue_giat f_ma_es m_la_esuada p_er_tium e_eg_stas.

Sie können benannte Gruppen auch für Ersetzungen verwenden ${name}.

Um mit Regex zu spielen, empfehle ich http://regex101.com/, die eine gute Menge an Details zur Funktionsweise der Regex bietet; Es bietet auch ein paar Regex-Engines zur Auswahl.


1828
2017-08-18 15:39



Sie können Erfassungsgruppen verwenden, um einen Ausdruck zu organisieren und zu analysieren. Eine nicht einfangende Gruppe hat den ersten Vorteil, hat aber nicht den Overhead der Sekunde. Sie können immer noch sagen, dass eine nicht erfassende Gruppe zum Beispiel optional ist.

Angenommen, Sie möchten numerischen Text vergleichen, aber einige Zahlen könnten als 1., 2., 3., 4., ... geschrieben werden. Wenn Sie den numerischen Teil, aber nicht das Suffix (optional) erfassen möchten, können Sie eine nicht erfassende Gruppe verwenden .

([0-9]+)(?:st|nd|rd|th)?

Das wird Zahlen in der Form 1, 2, 3 ... oder in der Form 1., 2., 3., ... entsprechen, aber es wird nur den numerischen Teil erfassen.


135
2017-08-18 13:24



?: wird verwendet, wenn Sie einen Ausdruck gruppieren möchten, ihn jedoch nicht als übereinstimmenden / erfassten Teil der Zeichenfolge speichern möchten.

Ein Beispiel wäre etwas, das einer IP-Adresse entspricht:

/(?:\d{1,3}\.){3}\d{1,3}/

Beachten Sie, dass es mir nicht wichtig ist, die ersten 3 Oktette zu speichern, sondern die (?:...) Gruppierung ermöglicht es mir, die Regex zu verkürzen, ohne den Aufwand für die Erfassung und Speicherung einer Übereinstimmung zu verursachen.


87
2017-08-18 13:22



Dadurch wird die Gruppe nicht erfasst, was bedeutet, dass die von dieser Gruppe übereinstimmende Teilzeichenfolge nicht in die Liste der Captures aufgenommen wird. Ein Beispiel in Ruby, um den Unterschied zu verdeutlichen:

"abc".match(/(.)(.)./).captures #=> ["a","b"]
"abc".match(/(?:.)(.)./).captures #=> ["b"]

27
2017-08-18 13:23



HISTORISCHE MOTIVATION: Die Existenz nicht einfangender Gruppen kann mit Hilfe von Klammern erklärt werden. Betrachten Sie die Ausdrücke (a | b) c und a | bc, da diese Ausdrücke wegen der Priorität der Verkettung über | zwei verschiedene Sprachen ({ac, bc} bzw. {a, bc}) darstellen. Die Klammern werden jedoch auch als übereinstimmende Gruppe verwendet (wie durch die anderen Antworten erläutert ...).

Wenn Sie Klammern haben möchten, aber den Unterausdruck nicht erfassen möchten, verwenden Sie NON-CAPTURING GROUPS. Im Beispiel (?: A | b) c


13
2018-02-04 08:07



Gruppiert das Erfassung Sie können später in der Regex verwenden, um zu passen ODER Sie können sie im Ersatzteil der Regex verwenden. Making a nicht erfassend Die Gruppe stellt diese Gruppe einfach davon frei, aus einem dieser Gründe verwendet zu werden.

Nicht erfassende Gruppen sind großartig, wenn Sie versuchen, viele verschiedene Dinge zu erfassen, und es gibt einige Gruppen, die Sie nicht erfassen möchten.

Das ist so ziemlich der Grund, warum sie existieren. Während du über Gruppen lernst, lerne etwas darüber Atomare Gruppensie machen viel! Es gibt auch Lookaround-Gruppen, aber sie sind ein wenig komplexer und nicht so oft verwendet.

Beispiel für die spätere Verwendung in der Regex (Rückreferenz):

<([A-Z][A-Z0-9]*)\b[^>]*>.*?</\1>  [Findet ein xml-Tag (ohne ns-Unterstützung)]

([A-Z][A-Z0-9]*) ist eine einfangende Gruppe (in diesem Fall ist es der Tagname)

Später in der Regex ist \1 Das bedeutet, dass nur der gleiche Text wie in der ersten Gruppe (der ([A-Z][A-Z0-9]*) Gruppe) (in diesem Fall entspricht es dem End-Tag).


12
2017-08-18 13:22



Lassen Sie mich das an einem Beispiel versuchen:

Regex-Code: - (?:animal)(?:=)(\w+)(,)\1\2

Suchbegriff :-

Linie 1 - Tier = Katze, Hund, Katze, Tiger, Hund

Linie 2 - Tier = Katze, Katze, Hund, Hund, Tiger

Zeile 3 - Tier = Hund, Hund, Katze, Katze, Tiger

(?:animal) -> Nicht erfasste Gruppe 1

(?:=)-> Nicht erfasste Gruppe 2

(\w+)-> Erfasste Gruppe 1

(,)-> Erfasste Gruppe 2

\1 -> Ergebnis der erfassten Gruppe 1, d. h. in Zeile 1 ist Katze, in Zeile 2 ist Katze, in Zeile 3 ist Hund.

\2 -> Ergebnis der erfassten Gruppe 2, d. h. Komma (,)

Also rufen wir in diesem Code mit \ 1 und \ 2 auf oder wiederholen das Ergebnis der eingefangenen Gruppe 1 bzw. 2 später im Code.

Nach der Reihenfolge des Codes (?: Tier) sollte Gruppe 1 sein und (?: =) Sollte Gruppe 2 sein und fortfährt ..

aber indem wir das?: geben wir die Match-Gruppe nicht erfasst (die nicht in der Matched-Gruppe abzählen, so dass die Gruppennummer beginnt von der ersten gefangenen Gruppe und nicht die nicht gefangenen), so dass die Wiederholung des Ergebnisses der Übereinstimmung -group (?: animal) kann später im Code nicht aufgerufen werden.

Hoffe das erklärt die Verwendung von nicht einfangenden Gruppe.

Bildbeschreibung hier eingeben


8
2018-01-19 11:36



Nun, ich bin ein JavaScript-Entwickler und werde versuchen, seine Bedeutung in Bezug auf JavaScript zu erklären.

Stellen Sie sich ein Szenario vor, in dem Sie übereinstimmen möchten cat is animal wenn Sie Katze und Tier zusammenbringen möchten und beide eine haben sollten is dazwischen.

 // this will ignore "is" as that's is what we want
"cat is animal".match(/(cat)(?: is )(animal)/) ;
result ["cat is animal", "cat", "animal"]

 // using lookahead pattern it will match only "cat" we can
 // use lookahead but the problem is we can not give anything
 // at the back of lookahead pattern
"cat is animal".match(/cat(?= is animal)/) ;
result ["cat"]

 //so I gave another grouping parenthesis for animal
 // in lookahead pattern to match animal as well
"cat is animal".match(/(cat)(?= is (animal))/) ;
result ["cat", "cat", "animal"]

 // we got extra cat in above example so removing another grouping
"cat is animal".match(/cat(?= is (animal))/) ;
result ["cat", "animal"]

6
2018-03-01 09:43