Wat is een niet-vastleggende groep in reguliere expressies?

Hoe worden niet-vastleggende groepen, d.w.z. (?:), gebruikt in reguliere expressies en waar zijn ze goed voor?


Antwoord 1, autoriteit 100%

Laat me proberen dit uit te leggen met een voorbeeld.

Beschouw de volgende tekst:

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

Als ik nu de onderstaande regex erop toepas…

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

… Ik zou het volgende resultaat krijgen:

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

Maar het protocol maakt me niet uit — ik wil alleen de host en het pad van de URL. Dus ik verander de regex om de niet-vastleggende groep (?:)op te nemen.

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

Mijn resultaat ziet er nu als volgt uit:

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

Zie je? De eerste groep is niet gevangen genomen. De parser gebruikt het om de tekst te matchen, maar negeert het later in het uiteindelijke resultaat.


BEWERKEN:

Laat me, zoals gevraagd, ook proberen groepen uit te leggen.

Nou, Groepen dienen veel doeleinden. Ze kunnen u helpen om exacte informatie uit een grotere match (die ook kan worden genoemd), laten ze u een vorige overeenkomende groep roepen en kan worden gebruikt voor substituties. Laten we enkele voorbeelden proberen, zullen wij?

Stel je voor dat je een soort XML of HTML hebt (Houd er rekening mee dat Regex is misschien niet de beste tool voor de baan , maar het is leuk als een voorbeeld). Je wilt de tags ontleden, zodat je zoiets zou kunnen doen (ik heb spaties toegevoegd om het gemakkelijker te begrijpen):

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

De eerste regex heeft een naam groep (tag), terwijl de tweede een gemeenschappelijke groep gebruikt. Beide regexes doen hetzelfde: ze gebruiken de waarde van de eerste groep (de naam van de tag) die overeenkomt met de sluitplaat. Het verschil is dat de eerste de naam gebruikt die overeenkomt met de waarde en de tweede gebruikt de groepsindex (die begint bij 1).

Laten we nu enige substituties proberen. Overweeg de volgende tekst:

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

Laten we deze domme regex erover gebruiken:

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

Deze regex komt overeen met woorden met minstens 3 tekens en gebruikt groepen om de eerste drie letters te scheiden. Het resultaat is dit:

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"
...

Dus, als we de vervangende string toepassen:

$1_$3$2_$4

…overheen proberen we de eerste groep te gebruiken, een onderstrepingsteken toe te voegen, de derde groep te gebruiken, dan de tweede groep, nog een onderstrepingsteken toe te voegen, en dan de vierde groep. De resulterende string zou zijn zoals die hieronder.

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.

Je kunt ook benoemde groepen gebruiken voor vervangingen met ${name}.

Om met regexen te spelen, raad ik http://regex101.com/aan, dat een goede hoeveelheid details over hoe de regex werkt; het biedt ook een paar regex-engines om uit te kiezen.


Antwoord 2, autoriteit 8%

U kunt vastleggingsgroepen gebruiken om een uitdrukking te ordenen en te ontleden. Een niet-vastleggende groep heeft het eerste voordeel, maar niet de overhead van het tweede. Je kunt bijvoorbeeld nog steeds zeggen dat een niet-vastleggende groep optioneel is.

Stel dat u numerieke tekst wilt matchen, maar sommige getallen kunnen worden geschreven als 1e, 2e, 3e, 4e,… Als u het numerieke gedeelte wilt vastleggen, maar niet het (optionele) achtervoegsel, kunt u een niet -vastleggende groep.

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

Dat komt overeen met getallen in de vorm 1, 2, 3… of in de vorm 1e, 2e, 3e,… maar het zal alleen het numerieke deel vastleggen.


Antwoord 3, autoriteit 5%

?:wordt gebruikt wanneer u een uitdrukking wilt groeperen, maar deze niet wilt opslaan als een overeenkomend/vastgelegd gedeelte van de tekenreeks.

Een voorbeeld is iets dat overeenkomt met een IP-adres:

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

Merk op dat het mij niet uitmaakt of ik de eerste 3 octetten bewaar, maar de (?:...)-groepering stelt me in staat de regex in te korten zonder de overhead van het vastleggen en opslaan van een wedstrijd .


Antwoord 4, autoriteit 2%

Het maakt de groep niet-vastleggend, wat betekent dat de substring die overeenkomt met die groep niet zal worden opgenomen in de lijst met vastleggingen. Een voorbeeld in robijn om het verschil te illustreren:

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

Antwoord 5, autoriteit 2%

HISTORISCHE MOTIVATIE:

Het bestaan van niet-vastleggende groepen kan worden verklaard met behulp van haakjes.

Beschouw de uitdrukkingen (a|b)cen a|bc, vanwege de prioriteit van aaneenschakeling boven |, deze uitdrukkingen vertegenwoordigen twee verschillende talen (respectievelijk {ac, bc}en {a, bc}).

De haakjes worden echter ook gebruikt als een overeenkomende groep (zoals uitgelegd door de andere antwoorden…).

Als u haakjes wilt hebben maar de sub-expressie niet wilt vastleggen, gebruikt u NON-CAPTURING GROEPEN. In het voorbeeld (?:a|b)c


Antwoord 6

Laat me dit proberen met een voorbeeld:

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

Zoekreeks:

Lijn 1 – animal=cat,dog,cat,tiger,dog

Lijn 2 – animal=cat,cat,dog,dog,tiger

Regel 3 – animal=dog,dog,cat,cat,tiger

(?:animal)–> Niet-vastgelegde groep 1

(?:=)–> Niet-vastgelegde groep 2

(\w+)– & GT; Gevangen groep 1

(,)– & GT; Geplaatst groep 2

\1– & GT; Resultaat van gevangengroep 1 I.E in lijn 1 is kat, in lijn 2 is kat, in lijn 3 is een hond.

\2– & GT; Resultaat van vastgelegde groep 2 I.E-komma (,)

Dus in deze code door \1en \2te geven of het resultaat van vastgelegde groep 1 en 2 later in de code te herhalen.

volgens de volgorde van Code (?:animal)moet groep 1 en (?:=)moeten groep 2 zijn en vervolgt ..

Maar door de ?:Wij maken de Match-Group niet vastgelegd (die niet aftellen in de gematchte groep, zodat het groeperingsnummer begint met de eerste gevangengroep en niet de niet-vastgelopen groep en niet de niet-vastgelopen groep) , zodat de herhaling van het resultaat van match-groep (?:animal)niet later in de code kan worden genoemd.

Ik hoop dat dit het gebruik van niet-vastleggroep uitlegt.


Antwoord 7

Groepen die Capture U kunt later in de regex gebruiken om te matchen of U kunt ze gebruiken in het vervangende deel van de regex. Het maken van een Niet-vastleggen Group vrijmaakt gewoon die groep om om een ​​van deze redenen te worden gebruikt.

Niet-vastleggende groepen zijn geweldig als u probeert veel verschillende dingen te vangen en er zijn enkele groepen die u niet wilt vastleggen.

Dat is vrijwel de reden waarom ze bestaan. Terwijl je over groepen leert, leer je dan atomic groepen , ze doen veel! Er is ook uitzietige groepen, maar ze zijn een beetje complexer en niet zoveel gebruikt.

Voorbeeld van later gebruik in de regex (terugverwijzing):

<([A-Z][A-Z0-9]*)\b[^>]*>.*?</\1>[ Vindt een xml-tag ( zonder ns-ondersteuning) ]

([A-Z][A-Z0-9]*)is een capture-groep (in dit geval is het de tagnaam)

Later in de regex staat \1, wat betekent dat het alleen overeenkomt met dezelfde tekst die in de eerste groep stond (de ([A-Z][A-Z0-9]*)groep) (in dit geval komt het overeen met de eindtag).


Antwoord 8

tl;drniet-vastleggende groepen, zoals de naam al doet vermoeden, zijn de delen van de regex die u niet wilt opnemen in de wedstrijd en ?:is een manier om een groep te definiëren als niet-vastleggend.

Stel dat je een e-mailadres [email protected]hebt. De volgende regex maakt twee groepen, het id-gedeelte en het @example.com-gedeelte. (\p{Alpha}*[a-z])(@example.com). Voor de eenvoud extraheren we de hele domeinnaam inclusief het teken @.

Laten we zeggen dat je alleen het id-gedeelte van het adres nodig hebt. Wat u wilt doen, is de eerste groep van het wedstrijdresultaat pakken, omringd door ()in de regex en de manier om dit te doen is door de syntaxis van de niet-vastleggende groep te gebruiken, dwz ?:. Dus de regex (\p{Alpha}*[a-z])(?:@example.com)retourneert alleen het id-gedeelte van de e-mail.


Antwoord 9

Ik kan geen commentaar geven op de beste antwoorden om dit te zeggen: ik wil graag een expliciet punt toevoegen dat alleen wordt geïmpliceerd in de beste antwoorden:

De niet-vangende groep (?...)
verwijdert geentekens uit de originele volledige overeenkomst, het reorganiseert alleende regex visueel naar de programmeur.

Om toegang te krijgen tot een specifiek deel van de regex zonder gedefinieerde vreemde tekens, moet u altijd .group(<index>)

gebruiken


Antwoord 10

Nou, ik ben een JavaScript-ontwikkelaar en zal proberen de betekenis ervan met betrekking tot JavaScript uit te leggen.

Bedenk een scenario waarin je cat is animalwilt matchen
wanneer je een match kat en dier wilt en beide een isertussen moeten hebben.

// 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"]

Antwoord 11

In complexe reguliere expressies kan de situatie ontstaan waarin u een groot aantal groepen wilt gebruiken, waarvan sommige er zijn voor herhalingsmatching en sommige er zijn om terugverwijzingen te geven. Standaard wordt de tekst die overeenkomt met elke groep in de backreference-array geladen. Waar we veel groepen hebben en slechts naar enkele van hen hoeven te verwijzen vanuit de backreference-array, kunnen we dit standaardgedrag overschrijven om de reguliere expressie te vertellen dat bepaalde groepen er alleen zijn voor herhalingsafhandeling en niet hoeven te worden vastgelegd en opgeslagen in de backreferentie-array.


Antwoord 12

Een interessant ding dat ik tegenkwam, is het feit dat je een vastleggende groep kunt hebben binnen een niet-vastleggende groep. Bekijk de onderstaande regex voor overeenkomende web-urls:

var parse_url_regex = /^(?:([A-Za-z]+):)(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;

Invoer URL-tekenreeks:

var url = "http://www.ora.com:80/goodparts?q#fragment";

De eerste groep in mijn regex (?:([A-Za-z]+):)is een niet-vastleggende groep die overeenkomt met het protocolschema en de dubbele punt :teken dwz http:maar toen ik onderstaande code uitvoerde, zag ik dat de eerste index van de geretourneerde array de string httpbevatte toen ik dacht dat httpen dubbele punt :beide worden niet gerapporteerd omdat ze deel uitmaken van een niet-vastleggende groep.

console.debug(parse_url_regex.exec(url));

Ik dacht dat als de eerste groep (?:([A-Za-z]+):)een niet-vastleggende groep is, waarom deze dan httpretourneert tekenreeks in de uitvoerarray.

Dus als je merkt dat er een geneste groep ([A-Za-z]+)is binnen de niet-vastleggende groep. Die geneste groep ([A-Za-z]+)is een vanggroep (zonder ?:aan het begin) op zichzelf binnen een niet-overnemende groep (?:([A-Za-z]+):). Dat is de reden waarom de tekst httpnog steeds wordt vastgelegd, maar het dubbele punt :dat zich binnen de niet-vastleggende groep maar buiten de vastleggroep bevindt, wordt niet gerapporteerd in de uitvoerarray.


Antwoord 13

Het is uiterst eenvoudig, we kunnen het begrijpen met een eenvoudig datumvoorbeeld, stel dat als de datum wordt vermeld als 1 januari 2019 of 2 mei 2019 of een andere datum en we deze gewoon willen converteren naar dd/mm/jjjj-indeling hebben we de naam van de maand niet nodig, wat overigens januari of februari is, dus om het numerieke gedeelte vast te leggen, maar niet het (optionele) achtervoegsel, kunt u een niet-vastleggende groep gebruiken.

dus de reguliere expressie zou zijn,

([0-9]+)(?:January|February)?

Zo simpel is het.


Antwoord 14

Ik denk dat ik je het antwoord zou geven. Gebruik geen capture-variabelen zonder te controleren of de match geslaagd is.

De capture-variabelen, $1, enz., zijn niet geldig tenzij de overeenkomst is geslaagd, en ze worden ook niet gewist.

#!/usr/bin/perl  
use warnings;
use strict;   
$_ = "bronto saurus burger";
if (/(?:bronto)? saurus (steak|burger)/)
{
    print "Fred wants a  $1";
}
else
{
    print "Fred dont wants a $1 $2";
}

In het bovenstaande voorbeeld, om te voorkomen dat bronto wordt vastgelegd in $1, wordt (?:)gebruikt.

Als het patroon overeenkomt, wordt $1vastgelegd als het volgende gegroepeerde patroon.

Dus de uitvoer is als volgt:

Fred wants a burger

Het is handig als u niet wilt dat de overeenkomsten worden opgeslagen.


Antwoord 15

Open uw Google Chrome devTools en vervolgens het tabblad Console: en typ dit:

"Peace".match(/(\w)(\w)(\w)/)

Voer het uit en je zult zien:

["Pea", "P", "e", "a", index: 0, input: "Peace", groups: undefined]

De JavaScriptRegExp-engine legt drie groepen vast, de items met indexen 1,2,3. Gebruik nu niet-vastleggende markering om het resultaat te zien.

"Peace".match(/(?:\w)(\w)(\w)/)

Het resultaat is:

["Pea", "e", "a", index: 0, input: "Peace", groups: undefined]

Dit is duidelijk wat een niet-vastleggende groep is.


Antwoord 16

Een eenvoudig antwoord

Gebruik ze om ervoor te zorgen dat een van de verschillende mogelijkheden hier (?:one|two)of een optionele zin camp(?:site)?of in het algemeen, waar dan ook voorkomt je wilt verwijzen naar een groep/zin/sectie zonder er specifiek naar te hoeven verwijzen.

Ze houden het aantal gevangengenomen groepen tot een minimum beperkt.


Antwoord 17

(?: … ) fungeert als een groep ( … ) maar legt de overeenkomende gegevens niet vast. Het is echt veel efficiënter dan een standaard capture-groep. Het wordt gebruikt wanneer u iets wilt groeperen, maar het later niet opnieuw hoeft te gebruiken. @Toto

Other episodes