Je veux juste créer une expression régulière à partir de toute chaîne possible.
_var usersString = "Hello?!*`~World()[]";
var expression = new RegExp(RegExp.escape(usersString))
var matches = "Hello".match(expression);
_
Existe-t-il une méthode intégrée pour cela? Si non, qu'est-ce que les gens utilisent? Ruby a RegExp.escape
. Je ne pense pas que j'aurais besoin d'écrire le mien, il doit y avoir quelque chose de standard là-bas. Merci!
La fonction liée ci-dessus est insuffisante. Il ne parvient pas à échapper à ^
ou $
(début et fin de chaîne), ni à -
qui, dans un groupe de caractères, est utilisé pour les plages.
Utilisez cette fonction:
RegExp.escape= function(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};
Bien que cela puisse sembler inutile à première vue, échapper à -
(ainsi que ^
) rend la fonction appropriée pour que des caractères d'échappement soient insérés dans une classe de caractères ainsi que dans le corps de l'expression régulière.
Echap /
rend la fonction appropriée pour les caractères d'échappement à utiliser dans un littéral de regex JS pour une évaluation ultérieure.
Comme il n’ya aucun inconvénient à échapper à l’un ou à l’autre, il est logique de s’échapper pour couvrir des cas d’utilisation plus larges.
Et oui, il est décevant de constater que cela ne fait pas partie de JavaScript standard.
Pour ceux qui utilisent lodash, depuis la v3.0. a _. EscapeRegExp la fonction est intégrée:
_.escapeRegExp('[lodash](https://lodash.com/)');
// → '\[lodash\]\(https:\/\/lodash\.com\/\)'
Et, au cas où vous ne voudriez pas avoir besoin de la bibliothèque complète de lodash, vous pourriez avoir besoin de juste cette fonction !
La plupart des expressions ici résolvent des cas d'utilisation spécifiques.
Ce n'est pas grave, mais je préfère une approche "toujours efficace".
function regExpEscape(literal_string) {
return literal_string.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
}
Cela "échappera totalement" à une chaîne littérale pour l'une des utilisations suivantes dans les expressions régulières:
new RegExp(regExpEscape(str))
new RegExp('[' + regExpEscape(str) + ']')
new RegExp('x{1,' + regExpEscape(str) + '}')
Caractères spéciaux couverts:
-
: Crée une plage de caractères dans une classe de caractères.[
/]
: Commence/termine une classe de caractères.{
/}
: Démarre/termine un spécificateur de numération.(
/)
: Démarre/termine un groupe.*
/+
/?
: Spécifie le type de répétition..
: Correspond à n'importe quel caractère.\
: échappe aux caractères et démarre les entités.^
: spécifie le début de la zone de correspondance et annule la correspondance dans une classe de caractères.$
: Spécifie la fin de la zone correspondante.|
: Spécifie l'alternance.#
: Spécifie un commentaire en mode d'espacement libre.\s
: Ignoré en mode d'espacement libre.,
: Sépare les valeurs dans un spécificateur de numération./
: commence ou termine l'expression.:
: complète les types de groupes spéciaux et fait partie de classes de caractères de style Perl.!
: nie le groupe de largeur zéro.<
/=
: Partie des spécifications du groupe de largeur nulle.Remarques:
/
n'est pas strictement nécessaire dans une variante d'expression régulière. Cependant, il protège dans le cas où quelqu'un (frisson) fait eval("/" + pattern + "/");
.,
garantit que si la chaîne est censée être un entier dans le spécificateur numérique, elle provoquera correctement une erreur de compilation RegExp au lieu d'une compilation silencieuse erronée.#
, et \s
n'ont pas besoin d'être échappés en JavaScript, mais le font dans de nombreuses autres versions. Ils sont échappés ici au cas où l'expression régulière serait ultérieurement transmise à un autre programme.Si vous devez également assurer la pérennité de l'expression régulière par rapport aux ajouts potentiels aux capacités du moteur JavaScript regex, je vous recommande d'utiliser la méthode plus paranoïaque:
function regExpEscapeFuture(literal_string) {
return literal_string.replace(/[^A-Za-z0-9_]/g, '\\$&');
}
Cette fonction échappe à tous les caractères sauf ceux explicitement garantis, ne pas être utilisés pour la syntaxe dans les futurs types d’expressions régulières.
Pour ceux qui s'intéressent vraiment à l’assainissement, considérons ce cas Edge:
var s = '';
new RegExp('(choice1|choice2|' + regExpEscape(s) + ')');
Ceci devrait compile bien en JavaScript, mais ne le sera pas dans d’autres saveurs. Si l'intention est de passer à une autre version, le cas nul de s === ''
doit être vérifié indépendamment, comme suit:
var s = '';
new RegExp('(choice1|choice2' + (s ? '|' + regExpEscape(s) : '') + ')');
Guide des expressions régulières dans le réseau de développeurs Mozilla fournit cette fonction d'échappement:
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
Dans le widget autocomplete de jQueryUI (version 1.9.1), ils utilisent une expression rationnelle légèrement différente (ligne 6753). Voici l'expression régulière combinée avec l'approche @bobince.
RegExp.escape = function( value ) {
return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
}
Rien ne devrait vous empêcher d'échapper à tous les caractères non alphanumériques:
usersString.replace(/(?=\W)/g, '\\');
Lorsque vous faites re.toString()
, vous perdez un certain degré de lisibilité, mais vous gagnez beaucoup de simplicité (et de sécurité).
Selon ECMA-262, d’une part, les expressions régulières "caractères de syntaxe" sont toujours non alphanumériques, de sorte que le résultat est sécurisé, et les séquences d’échappement spéciales (\d
, \w
, \n
) sont toujours alphanumériques, de sorte qu’aucune fausse échappée de contrôle ne sera produite.
Il existe une proposition ES7 pour RegExp.escape à https://github.com/benjamingr/RexExp.escape/ , avec un polyfill disponible à https://github.com/ljharb /regexp.escape .
Ceci est une version plus courte.
RegExp.escape = function(s) {
return s.replace(/[$-\/?[-^{|}]/g, '\\$&');
}
Cela inclut les caractères non méta de %
, &
, '
et ,
, mais la spécification JavaScript RegExp le permet.
escapeRegExp = function(str) {
if (str == null) return '';
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
Plutôt que de simplement échapper des caractères susceptibles de générer des problèmes dans votre expression régulière (une liste noire, par exemple), pourquoi ne pas utiliser une liste blanche à la place. De cette façon, chaque personnage est considéré comme corrompu à moins qu'il ne corresponde.
Pour cet exemple, supposons l'expression suivante:
RegExp.escape('be || ! be');
Cette liste blanche lettres, nombre et espaces:
RegExp.escape = function (string) {
return string.replace(/([^\w\d\s])/gi, '\\$1');
}
Résultats:
"be \|\| \! be"
Cela peut échapper à des caractères qui ne doivent pas forcément être échappés, mais cela ne gêne pas votre expression (peut-être quelques pénalités de temps mineures, mais cela en vaut la peine pour la sécurité).
XRegExp a une fonction d'échappement:
XRegExp.escape('Escaped? <.>'); // -> 'Escaped\?\ <\.>'
Plus sur: http://xregexp.com/api/#escape
Une autre approche (beaucoup plus sûre) consiste à échapper à tous les caractères (et pas seulement à quelques-uns de ceux que nous connaissons actuellement) en utilisant le format d'échappement Unicode \u{code}
:
function escapeRegExp(text) {
return Array.from(text)
.map(char => `\\u{${char.charCodeAt(0).toString(16)}}`)
.join('');
}
console.log(escapeRegExp('a.b')); // '\u{61}\u{2e}\u{62}'
Veuillez noter que vous devez passer l'indicateur u
pour que cette méthode fonctionne:
var expression = new RegExp(escapeRegExp(usersString), 'u');
Les fonctions dans les autres réponses sont excessives pour échapper à des expressions régulières entières (elles peuvent être utiles pour échapper à parties d'expressions régulières qui seront ensuite concaténées dans de plus grandes expressions rationnelles).
Si vous échappez à une expression rationnelle entière et que vous en avez terminé, citez les métacaractères qui sont autonomes (.
, ?
, +
, *
, ^
, _ $
, |
, \
) ou démarrer quelque chose ((
, [
, {
) est tout ce dont vous avez besoin:
String.prototype.regexEscape = function regexEscape() {
return this.replace(/[.?+*^$|({[\\]/g, '\\$&');
};
Et oui, il est décevant que JavaScript n’ait pas une fonction comme celle-ci.