Regex: Recurcive Regex et balises Html

Les regex c’est bien ! C’est même génial. Mais il y a un truc qui n’est pas faisable : des patterns récursifs dans une chaine. (Il existe bien la syntaxe (?R) dans certains langages mais en javascript par exemple, il faut se débrouiller tout seul.

Problématique du jour: trouver dans une chaine les balises toutes les balises <span class= »… »>…</span>. Bien entendu, les balises peuvent être imbriquées. C’est là où les problèmes apparaissent.

Et c’est là que stevenlevithan nous donne la solution :

  1. // (c) 2007 Steven Levithan <stevenlevithan.com>
  2. // MIT License
  3.  
  4. /*** matchRecursiveRegExp
  5.  Accepts a string to search, a left and right format delimiter
  6.  as regex patterns, and optional regex flags. Returns an array
  7.  of matches, allowing nested instances of left/right delimiters.
  8.  Use the "g" flag to return all matches, otherwise only the
  9.  first is returned. Be careful to ensure that the left and
  10.  right format delimiters produce mutually exclusive matches.
  11.  Backreferences are not supported within the right delimiter
  12.  due to how it is internally combined with the left delimiter.
  13.  When matching strings whose format delimiters are unbalanced
  14.  to the left or right, the output is intentionally as a
  15.  conventional regex library with recursion support would
  16.  produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using
  17.  "<" and ">" as the delimiters (both strings contain a single,
  18.  balanced instance of "<x>").
  19.  
  20.  examples:
  21.   matchRecursiveRegExp("test", "\\(", "\\)")
  22.    returns: []
  23.   matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g")
  24.    returns: ["t<<e>><s>", ""]
  25.   matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi")
  26.    returns: ["test"]
  27.  
  28. */
  29. function matchRecursiveRegExp (str, left, right, flags) {
  30.  var f = flags || "",
  31.   g = f.indexOf("g") > -1,
  32.   x = new RegExp(left + "|" + right, "g" + f),
  33.   l = new RegExp(left, f.replace(/g/g, "")),
  34.   a = [],
  35.   t, s, m;
  36.  
  37.  do {
  38.   t = 0;
  39.   while (m = x.exec(str)) {
  40.    if (l.test(m[0])) {
  41.     if (!t++) s = x.lastIndex;
  42.    } else if (t) {
  43.     if (!–t) {
  44.      a.push(str.slice(s, m.index));
  45.      if (!g) return a;
  46.     }
  47.    }
  48.   }
  49.  } while (t && (x.lastIndex = s));
  50.  
  51.  return a;
  52. }

Le commentaires sont fermés.