web-dev-qa-db-fra.com

Comment capturer un nombre arbitraire de groupes dans JavaScript Regexp?

Je m'attendrais à cette ligne de JavaScript:

"foo bar baz".match(/^(\s*\w+)+$/)

pour retourner quelque chose comme:

["foo bar baz", "foo", " bar", " baz"]

mais à la place, il ne renvoie que la dernière correspondance capturée:

["foo bar baz", " baz"]

Existe-t-il un moyen d'obtenir tous les matchs capturés?

75
disc0dancer

Lorsque vous répétez un groupe de capture, dans la plupart des versions, seule la dernière capture est conservée; toute capture précédente est remplacée. Dans une certaine saveur, par exemple .NET, vous pouvez obtenir toutes les captures intermédiaires, mais ce n'est pas le cas avec Javascript.

Autrement dit, en Javascript, si vous avez un modèle avec [~ # ~] n [~ # ~] capturer des groupes, vous ne pouvez capturer exactement [~ # ~] n [~ # ~] chaînes par correspondance, même si certains de ces groupes ont été répétés.

Donc, d'une manière générale, selon ce que vous devez faire:

  • Si c'est une option, divisez plutôt les délimiteurs
  • Au lieu de faire correspondre /(pattern)+/, peut-être correspondre à /pattern/g, peut-être dans une boucle exec
    • Notez que ces deux ne sont pas exactement équivalents, mais cela peut être une option
  • Faire une correspondance à plusieurs niveaux:
    • Capturez le groupe répété en une seule partie
    • Ensuite, exécutez une autre expression régulière pour briser ce match

Les références


Exemple

Voici un exemple de correspondance <some;words;here> dans un texte, en utilisant une boucle exec, puis en divisant sur ; pour obtenir des mots individuels ( voir aussi sur ideone.com ):

var text = "a;b;<c;d;e;f>;g;h;i;<no no no>;j;k;<xx;yy;zz>";

var r = /<(\w+(;\w+)*)>/g;

var match;
while ((match = r.exec(text)) != null) {
  print(match[1].split(";"));
}
// c,d,e,f
// xx,yy,zz

Le modèle utilisé est:

      _2__
     /    \
<(\w+(;\w+)*)>
 \__________/
      1

Cela correspond à <Word>, <Word;another>, <Word;another;please>, etc. Le groupe 2 est répété pour capturer n'importe quel nombre de mots, mais il ne peut conserver que la dernière capture. La liste complète des mots est capturée par le groupe 1; cette chaîne est alors split sur le délimiteur point-virgule.

Questions connexes

83
polygenelubricants

Et ça? "foo bar baz".match(/(\w+)+/g)

7
meder omuraliev

Sauf si vous avez une exigence plus compliquée sur la façon dont vous fractionnez vos chaînes, vous pouvez les fractionner, puis renvoyer la chaîne initiale avec elles:

var data = "foo bar baz";
var pieces = data.split(' ');
pieces.unshift(data);
5
g.d.d.c

essayez d'utiliser 'g':

"foo bar baz".match(/\w+/g)
4
Jet