165 Stimmen

Wie kann ich mehrere Vorkommen mit einer Regex in JavaScript abgleichen, ähnlich wie bei PHP's preg_match_all()?

Ich versuche, url-codierte Zeichenfolgen zu analysieren, die aus Schlüssel=Wert-Paaren bestehen, die entweder durch & o & .

Im Folgenden wird nur das erste Vorkommen abgeglichen, wobei die Schlüssel und Werte in separate Ergebniselemente aufgeteilt werden:

var result = mystring.match(/(?:&|&)?([^=]+)=([^&]+)/)

Die Ergebnisse für die Zeichenfolge '1111342=Adam%20Franco&348572=Bob%20Jones' wären:

['1111342', 'Adam%20Franco']

Mit dem globalen Flag 'g' werden alle Vorkommen abgeglichen, aber nur die vollständig übereinstimmenden Teilstrings zurückgegeben, nicht die getrennten Schlüssel und Werte:

var result = mystring.match(/(?:&|&)?([^=]+)=([^&]+)/g)

Die Ergebnisse für die Zeichenfolge '1111342=Adam%20Franco&348572=Bob%20Jones' wären:

['1111342=Adam%20Franco', '&348572=Bob%20Jones']

Während ich die Zeichenkette aufteilen könnte & und jedes Schlüssel/Wert-Paar einzeln aufschlüsseln, gibt es eine Möglichkeit, mit der JavaScript-Unterstützung für reguläre Ausdrücke auf mehrere Vorkommen des Musters /(?:&|&)?([^=]+)=([^&]+)/ ähnlich wie PHPs preg_match_all() Funktion?

Ich suche nach einer Möglichkeit, Ergebnisse zu erhalten, bei denen die Unterübereinstimmungen getrennt sind:

[['1111342', '348572'], ['Adam%20Franco', 'Bob%20Jones']]

o

[['1111342', 'Adam%20Franco'], ['348572', 'Bob%20Jones']]

9 Stimmen

Es ist ein wenig seltsam, dass niemand die Verwendung von replace hier. var data = {}; mystring.replace(/(?:&|&)?([^=]+)=([^&]+)/g, function(a,b,c,d) { data[c] = d; }); erledigt. "matchAll" in JavaScript ist "replace" mit einer Ersetzungsfunktion anstelle einer Zeichenkette.

0 Stimmen

Für diejenigen, die diese Frage im Jahr 2020 immer noch nicht beantworten können, lautet die Antwort: "Don't use regex, use URLSearchParams die all dies für Sie erledigt."

12voto

KIM Taegyoon Punkte 1777

Quelle:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec

Suche nach aufeinanderfolgenden Übereinstimmungen

Wenn Ihr regulärer Ausdruck das "g"-Flag verwendet, können Sie die exec()-Methode mehrfach verwenden, um aufeinanderfolgende Übereinstimmungen in derselben Zeichenfolge zu finden. Dabei beginnt die Suche bei der Teilzeichenkette von str, die durch die Eigenschaft lastIndex des regulären Ausdrucks angegeben ist (test() setzt die Eigenschaft lastIndex ebenfalls fort). Nehmen wir zum Beispiel an, Sie haben dieses Skript:

var myRe = /ab*/g;
var str = 'abbcdefabh';
var myArray;
while ((myArray = myRe.exec(str)) !== null) {
  var msg = 'Found ' + myArray[0] + '. ';
  msg += 'Next match starts at ' + myRe.lastIndex;
  console.log(msg);
}

Dieses Skript zeigt den folgenden Text an:

Found abb. Next match starts at 3
Found ab. Next match starts at 912

Hinweis: Platzieren Sie das Literal des regulären Ausdrucks (oder den RegExp-Konstruktor) nicht innerhalb der while-Bedingung, da sonst eine Endlosschleife entsteht, wenn es eine Übereinstimmung gibt, da die Eigenschaft lastIndex bei jeder Iteration zurückgesetzt wird. Stellen Sie außerdem sicher, dass das globale Flag gesetzt ist, da sonst auch hier eine Schleife entsteht.

0 Stimmen

Wenn ich aufrufe, um diesen Code zu validieren myRe.test(str) und dann versuchen, tun, während, es Sterne bei zweiten Spiel und wir verloren das erste Spiel.

0 Stimmen

Sie können auch kombinieren String.prototype.match mit dem g Flagge: 'abbcdefabh'.match(/ab*/g) gibt zurück. ['abb', 'ab']

4voto

Klesun Punkte 9663

Hallo ab 2020. Lassen Sie mich bringen String.prototype.matchAll() zu Ihrer Kenntnis:

let regexp = /(?:&|&)?([^=]+)=([^&]+)/g;
let str = '1111342=Adam%20Franco&348572=Bob%20Jones';

for (let match of str.matchAll(regexp)) {
    let [full, key, value] = match;
    console.log(key + ' => ' + value);
}

Ausgänge:

1111342 => Adam%20Franco
348572 => Bob%20Jones

0 Stimmen

Endlich! Ein Hinweis zur Vorsicht: "ECMAScript 2020, die 11. Ausgabe, führt die matchAll-Methode für Strings ein, um einen Iterator für alle durch einen globalen regulären Ausdruck erzeugten Match-Objekte zu erzeugen. . Nach der Website in der Antwort verlinkt, die meisten Browser & nodeJS unterstützen es derzeit, aber nicht IE, Safari, oder Samsung Internet. Hoffentlich Unterstützung wird bald zu erweitern, aber YMMV für eine Weile.

2voto

fedu Punkte 138

Wenn jemand (wie ich) Tomalaks Methode mit Array-Unterstützung (d.h. Mehrfachauswahl) benötigt, hier ist sie:

function getUrlParams(url) {
  var re = /(?:\?|&(?:amp;)?)([^=&#]+)(?:=?([^&#]*))/g,
      match, params = {},
      decode = function (s) {return decodeURIComponent(s.replace(/\+/g, " "));};

  if (typeof url == "undefined") url = document.location.href;

  while (match = re.exec(url)) {
    if( params[decode(match[1])] ) {
        if( typeof params[decode(match[1])] != 'object' ) {
            params[decode(match[1])] = new Array( params[decode(match[1])], decode(match[2]) );
        } else {
            params[decode(match[1])].push(decode(match[2]));
        }
    }
    else
        params[decode(match[1])] = decode(match[2]);
  }
  return params;
}
var urlParams = getUrlParams(location.search);

Eingabe ?my=1&my=2&my=things

Ergebnis 1,2,things (früher nur zurückgegeben: Dinge)

1voto

Chris West Punkte 865

Um bei der vorgeschlagenen Frage zu bleiben, wie im Titel angedeutet, können Sie tatsächlich über jede Übereinstimmung in einer Zeichenfolge iterieren, indem Sie String.prototype.replace() . Das folgende Beispiel zeigt genau das, um ein Array aller Wörter auf der Grundlage eines regulären Ausdrucks zu erhalten:

function getWords(str) {
  var arr = [];
  str.replace(/\w+/g, function(m) {
    arr.push(m);
  });
  return arr;
}

var words = getWords("Where in the world is Carmen Sandiego?");
// > ["Where", "in", "the", "world", "is", "Carmen", "Sandiego"]

Wenn ich Erfassungsgruppen oder sogar den Index jeder Übereinstimmung erhalten wollte, könnte ich das auch tun. Im Folgenden wird gezeigt, wie jede Übereinstimmung mit der gesamten Übereinstimmung, der ersten Erfassungsgruppe und dem Index zurückgegeben wird:

function getWords(str) {
  var arr = [];
  str.replace(/\w+(?=(.*))/g, function(m, remaining, index) {
    arr.push({ match: m, remainder: remaining, index: index });
  });
  return arr;
}

var words = getWords("Where in the world is Carmen Sandiego?");

Nach der Ausführung der oben genannten, words werden wie folgt sein:

[
  {
    "match": "Where",
    "remainder": " in the world is Carmen Sandiego?",
    "index": 0
  },
  {
    "match": "in",
    "remainder": " the world is Carmen Sandiego?",
    "index": 6
  },
  {
    "match": "the",
    "remainder": " world is Carmen Sandiego?",
    "index": 9
  },
  {
    "match": "world",
    "remainder": " is Carmen Sandiego?",
    "index": 13
  },
  {
    "match": "is",
    "remainder": " Carmen Sandiego?",
    "index": 19
  },
  {
    "match": "Carmen",
    "remainder": " Sandiego?",
    "index": 22
  },
  {
    "match": "Sandiego",
    "remainder": "?",
    "index": 29
  }
]

Um mehrere Vorkommen abzugleichen, ähnlich wie es in PHP möglich ist mit preg_match_all Sie können diese Art des Denkens nutzen, um Ihre eigenen Ideen zu entwickeln, oder Sie können etwas wie YourJS.matchAll() . YourJS definiert diese Funktion mehr oder weniger wie folgt:

function matchAll(str, rgx) {
  var arr, extras, matches = [];
  str.replace(rgx.global ? rgx : new RegExp(rgx.source, (rgx + '').replace(/[\s\S]+\//g , 'g')), function() {
    matches.push(arr = [].slice.call(arguments));
    extras = arr.splice(-2);
    arr.index = extras[0];
    arr.input = extras[1];
  });
  return matches[0] ? matches : null;
}

0 Stimmen

Da Sie die Abfragezeichenfolge einer URL analysieren möchten, könnten Sie auch etwas wie YourJS.parseQS() ( yourjs.com/snippets/56 ), obwohl viele andere Bibliotheken diese Funktion ebenfalls anbieten.

0 Stimmen

Das Ändern einer Variablen aus einem äußeren Bereich in einer Schleife, die eine Ersetzung zurückgeben soll, ist ziemlich schlecht. Sie missbrauchen replace hier

1voto

fboes Punkte 2029

Wenn Sie sich mit der Verwendung von map dies ist eine Vier-Zeilen-Lösung:

var mystring = '1111342=Adam%20Franco&348572=Bob%20Jones';

var result = mystring.match(/(&|&)?([^=]+)=([^&]+)/g) || [];
result = result.map(function(i) {
  return i.match(/(&|&)?([^=]+)=([^&]+)/);
});

console.log(result);

Nicht schön, nicht effizient, aber wenigstens kompakt ;)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X