Hoe kan ik overlappende strings matchen met regex?

Stel dat ik de string heb

"12345"

Als ik .match(/\d{3}/g)krijg, krijg ik maar één overeenkomst, "123". Waarom krijg ik [ "123", "234", "345" ]niet?


Antwoord 1, autoriteit 100%

De string#matchmet een globale vlag regex retourneert een array van overeenkomende substrings. De /\d{3}/gregex komt overeen en consumeert(=leest in de buffer en voert de index naar de positie direct na het momenteel overeenkomende teken) 3-cijferige reeks. Dus, na het “opeten” van 123, bevindt de index zich na 3, en de enige substring die nog over is om te ontleden is 45– geen overeenkomst hier .

Ik denk dat de techniek die wordt gebruikt op regex101.comook hier het overwegen waard is: gebruik een bewering met een breedte van nul (een positieve vooruitblik met een capture-groep) om alle posities binnen de invoerreeks te testen. Na elke test wordt de RegExp.lastIndex(het is een geheeltallige eigenschap voor lezen/schrijven van reguliere expressies die de index specificeert waarop de volgende overeenkomst moet worden gestart) wordt “handmatig” geavanceerd om een ​​oneindige lus te voorkomen.

Merk op dat het een techniek is die is geïmplementeerd in .NET (Regex.Matches), Python (re.findall), PHP (preg_match_all) , Ruby (String#scan) en kan ook in Java worden gebruikt.
Hier is een demo met matchAll:

var re = /(?=(\d{3}))/g;
console.log( Array.from('12345'.matchAll(re), x => x[1]) );

Snippet uitvouwen


Antwoord 2, autoriteit 92%

Je kunt dit niet alleen doen met een regex, maar je kunt aardig dichtbij komen:

var pat = /(?=(\d{3}))\d/g;
var results = [];
var match;
while ( (match = pat.exec( '1234567' ) ) != null ) { 
  results.push( match[1] );
}
console.log(results);

Snippet uitvouwen


Antwoord 3, autoriteit 52%

Als een uitdrukking overeenkomt, gebruikt deze gewoonlijkde tekens waarmee deze overeenkomt. Dus nadat de uitdrukking overeenkomt met 123, blijft er alleen 45over, wat niet overeenkomt met het patroon.

Other episodes