web-dev-qa-db-fra.com

Comment diviser une longue expression régulière en plusieurs lignes en JavaScript?

J'ai une très longue expression régulière que je souhaite scinder en plusieurs lignes dans mon code JavaScript afin de conserver une longueur de ligne de 80 caractères conformément aux règles de JSLint. C'est juste mieux pour lire, je pense . Voici un exemple de modèle:

var pattern = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
109
Nik Sumeiko

Vous pouvez le convertir en chaîne et créer l'expression en appelant new RegExp():

var myRE = new RegExp (['^(([^<>()[\]\\.,;:\\s@\"]+(\\.[^<>(),[\]\\.,;:\\s@\"]+)*)',
                        '|(\\".+\\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.',
                        '[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\\.)+',
                        '[a-zA-Z]{2,}))$'].join(''));

Remarques:

  1. lors de la conversion du expression littérale en une chaîne, vous devez échapper à toutes les barres obliques inverses, celles-ci étant utilisées lors de l'évaluation d'un chaîne littérale. (Voir le commentaire de Kayo pour plus de détails.)
  2. RegExp accepte les modificateurs comme second paramètre

    /regex/g => new RegExp('regex', 'g')

[Addition ES20xx (modèle marqué)]

Dans ES20xx, vous pouvez utiliser templates tagged . Voir l'extrait. 

Remarque: 

  • L’inconvénient est qu’il est impossible d’utiliser des espaces blancs dans la chaîne d’expression régulière (utilisez toujours \s, \s+, \s{1,x}, \t, \n, etc.).

(() => {
  const createRegExp = (str, opts) => 
    new RegExp(str.raw[0].replace(/\s/gm, ""), opts || "");
  const yourRE = createRegExp`
    ^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|
    (\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|
    (([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$`;
  console.log(yourRE);
  const anotherLongRE = createRegExp`
    (\byyyy\b)|(\bm\b)|(\bd\b)|(\bh\b)|(\bmi\b)|(\bs\b)|(\bms\b)|
    (\bwd\b)|(\bmm\b)|(\bdd\b)|(\bhh\b)|(\bMI\b)|(\bS\b)|(\bMS\b)|
    (\bM\b)|(\bMM\b)|(\bdow\b)|(\bDOW\b)
    ${"gi"}`;
  console.log(anotherLongRE);
})();

96
KooiInc

En élargissant la réponse @KooiInc, vous pouvez éviter d'échapper manuellement chaque caractère spécial en utilisant la propriété source de l'objet RegExp

Exemple:

var urlRegex= new RegExp(''
  + /(?:(?:(https?|ftp):)?\/\/)/.source     // protocol
  + /(?:([^:\n\r]+):([^@\n\r]+)@)?/.source  // user:pass
  + /(?:(?:www\.)?([^\/\n\r]+))/.source     // domain
  + /(\/[^?\n\r]+)?/.source                 // request
  + /(\?[^#\n\r]*)?/.source                 // query
  + /(#?[^\n\r]*)?/.source                  // anchor
);

ou si vous voulez éviter de répéter la propriété .source, vous pouvez le faire en utilisant la fonction Array.map():

var urlRegex= new RegExp([
  /(?:(?:(https?|ftp):)?\/\/)/      // protocol
  ,/(?:([^:\n\r]+):([^@\n\r]+)@)?/  // user:pass
  ,/(?:(?:www\.)?([^\/\n\r]+))/     // domain
  ,/(\/[^?\n\r]+)?/                 // request
  ,/(\?[^#\n\r]*)?/                 // query
  ,/(#?[^\n\r]*)?/                  // anchor
].map(function(r) {return r.source}).join(''));

Dans ES6, la fonction de carte peut être réduite à: .map(r => r.source)

89
korun

L'utilisation de chaînes dans new RegExp est difficile car vous devez échapper à toutes les barres obliques inverses. Vous pouvez écrire des expressions rationnelles plus petites et les concaténer.

Séparons cette regex

/^foo(.*)\bar$/

Nous utiliserons une fonction pour rendre les choses plus belles plus tard

function multilineRegExp(regs, options) {
    return new RegExp(regs.map(
        function(reg){ return reg.source; }
    ).join(''), options);
}

Et maintenant, basculons

var r = multilineRegExp([
     /^foo/,  // we can add comments too
     /(.*)/,
     /\bar$/
]);

Comme cela a un coût, essayez de construire la vraie expression régulière une seule fois, puis utilisez-la.

22
Riccardo Galli

Il manque dans la regex ci-dessus des barres obliques noires qui ne fonctionnent pas correctement. Donc, j'ai édité la regex. Veuillez considérer cette expression rationnelle qui fonctionne à 99,99% pour la validation des emails.

let EMAIL_REGEXP = 
new RegExp (['^(([^<>()[\\]\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\.,;:\\s@\"]+)*)',
                    '|(".+"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.',
                    '[0-9]{1,3}\])|(([a-zA-Z\\-0-9]+\\.)+',
                    '[a-zA-Z]{2,}))$'].join(''));
4
Anvesh Reddy

Il y a de bonnes réponses ici, mais pour être complet, il convient de mentionner la fonctionnalité d'héritage de Javascript avec la chaîne prototype . Quelque chose comme ceci illustre l'idée:

RegExp.prototype.append = function(re) {
  return new RegExp(this.source + re.source, this.flags);
};

let regex = /[a-z]/g
.append(/[A-Z]/)
.append(/[0-9]/);

console.log(regex); //=> /[a-z][A-Z][0-9]/g

1
James Donohue

Pour éviter le tableau join, vous pouvez également utiliser la syntaxe suivante:

var pattern = new RegExp('^(([^<>()[\]\\.,;:\s@\"]+' +
  '(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@' +
  '((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|' +
  '(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$');
1
andreasonny83

Personnellement, je choisirais une expression rationnelle moins compliquée:

/\S+@\S+\.\S+/

Bien sûr, c’est moins précis que votre modèle actuel, mais que voulez-vous accomplir? Essayez-vous de détecter les erreurs accidentelles que vos utilisateurs pourraient saisir ou craignez-vous que vos utilisateurs ne tentent d'entrer des adresses non valides? Si c'est le premier, j'opterais pour un modèle plus facile. Si c'est le dernier cas, une meilleure vérification en répondant à un courrier électronique envoyé à cette adresse pourrait être une meilleure option.

Cependant, si vous voulez utiliser votre modèle actuel, il serait (IMO) plus facile à lire (et à maintenir!) En le construisant à partir de sous-modèles plus petits, comme ceci:

var box1 = "([^<>()[\]\\\\.,;:\s@\"]+(\\.[^<>()[\\]\\\\.,;:\s@\"]+)*)";
var box2 = "(\".+\")";

var Host1 = "(\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])";
var Host2 = "(([a-zA-Z\-0-9]+\\.)+[a-zA-Z]{2,})";

var regex = new RegExp("^(" + box1 + "|" + box2 + ")@(" + Host1 + "|" + Host2 + ")$");
1
Bart Kiers

Vous pouvez simplement utiliser l'opération de chaîne.

var pattenString = "^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|"+
"(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|"+
"(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$";
var patten = new RegExp(pattenString);
0
Mubeena