将用户输入字符串转换为正则表达式


333

我正在设计HTML和JavaScript中的正则表达式测试器。用户将输入一个正则表达式,一个字符串,并通过单选按钮选择要测试的函数(例如,搜索,匹配,替换等),并且当该函数以指定的参数运行时,程序将显示结果。自然地,会有额外的文本框来替换额外的参数。

我的问题是从用户那里获取字符串并将其转换为正则表达式。如果我说他们不需要//在输入的正则表达式中包含,则他们不能设置标志,例如gi。因此,它们必须//在表达式周围包含,但是如何将字符串转换为正则表达式?它不能是文字,因为它是一个字符串,我不能将其传递给RegExp构造函数,因为它不是没有//s 的字符串。还有其他方法可以使用户输入字符串进入正则表达式吗?我是否必须使用来解析regex的字符串和标志,//然后以其他方式构造它?我应该让他们输入一个字符串,然后分别输入标志吗?

Answers:


611

使用RegExp对象构造函数从字符串创建正则表达式:

var re = new RegExp("a|b", "i");
// same as
var re = /a|b/i;

1
拥有带有输入字段的在线工具会很好
holms 2013年

61
以这种方式进行操作时,必须避免使用反斜杠,例如var re = new RegExp("\\w+");
JD Smith

12
@holms regex101.com也是一个出色的regex在线工具
Fran Herrero

2
我花了一段时间,看看有没有需要尾随斜杠
Gerfried

2
@JDSmith在您的示例中我不是故意的。我的意思是,如果您希望双引号成为正则表达式的一部分,并且硬编码的话,则需要转义双引号。显然,如果字符串位于<input>HTML标记之类的变量中,则所有这些都不适用。 var re = new RegExp("\"\\w+\"");是使用正则表达式构造一个硬编码的正则表达式的一个例子和双引号的逸出必要的。我在变量中使用字符串的意思是您可以这样做,var re = new RegExp(str);并且str可以包含双引号或反斜杠而不会出现问题。
路易斯·保罗

66
var flags = inputstring.replace(/.*\/([gimy]*)$/, '$1');
var pattern = inputstring.replace(new RegExp('^/(.*?)/'+flags+'$'), '$1');
var regex = new RegExp(pattern, flags);

要么

var match = inputstring.match(new RegExp('^/(.*?)/([gimy]*)$'));
// sanity check here
var regex = new RegExp(match[1], match[2]);

您应该考虑/\/识别到无效的输入。
Gumbo

8
或者让RegExp构造函数失败,“在正则表达式中跟踪\”,而不是编写复杂的解析器。
匿名

21

这里是单线: str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')

我是从NEX模块的Escape-string-regexp获取的

尝试一下:

escapeStringRegExp.matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
function escapeStringRegExp(str) {
    return str.replace(escapeStringRegExp.matchOperatorsRe, '\\$&');
}

console.log(new RegExp(escapeStringRegExp('example.com')));
// => /example\.com/

将标记的模板文字与标志一起使用:

function str2reg(flags = 'u') {
    return (...args) => new RegExp(escapeStringRegExp(evalTemplate(...args))
        , flags)
}

function evalTemplate(strings, ...values) {
    let i = 0
    return strings.reduce((str, string) => `${str}${string}${
        i < values.length ? values[i++] : ''}`, '')
}

console.log(str2reg()`example.com`)
// => /example\.com/u


9

在我的情况下,用户输入somethimes由定界符引起,有时不是。因此,我添加了另一种情况。

var regParts = inputstring.match(/^\/(.*?)\/([gim]*)$/);
if (regParts) {
    // the parsed pattern had delimiters and modifiers. handle them. 
    var regexp = new RegExp(regParts[1], regParts[2]);
} else {
    // we got pattern string without delimiters
    var regexp = new RegExp(inputstring);
}

3
您可以始终使用.split()函数代替长的正则表达式字符串。 regParts = inputstring.split('/')这将形成regParts[1]正则表达式字符串和regParts[2]定界符(假设正则表达式的设置为/.../gim)。您可以检查是否存在带有的定界符regParts[2].length < 0
Jaketr00 '16

3

我建议您还为特殊标志添加单独的复选框或文本字段。这样,很明显,用户不需要添加任何//。如果是替换,请提供两个文本字段。这将使您的生活更加轻松。

为什么?因为否则某些用户将添加//,而其他用户则不会。而且有些会产生语法错误。然后,在删除了//' 之后,您可能会得到一个语法上有效的正则表达式,该表达式与用户的意图完全不同,从而导致奇怪的行为(从用户的角度而言)。


2

当字符串无效或不包含标志等时,这也将起作用:

function regExpFromString(q) {
  let flags = q.replace(/.*\/([gimuy]*)$/, '$1');
  if (flags === q) flags = '';
  let pattern = (flags ? q.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1') : q);
  try { return new RegExp(pattern, flags); } catch (e) { return null; }
}

console.log(regExpFromString('\\bword\\b'));
console.log(regExpFromString('\/\\bword\\b\/gi'));
            


2

如果您确实要将字符串转换为正则表达式,请尝试使用以下函数:

function String2Regex(s){return new RegExp(s.match(/\/(.+)\/.*/)[1], s.match(/\/.+\/(.*)/)[1]);}

您可以这样使用它:

"abc".match(String2Regex("/a/g"))
> ["a"]

作为参考,这是格式化的和更现代的版本:

const String2Regex = str => {
  // Main regex
  const main = str.match(/\/(.+)\/.*/)[1]

  // Regex options
  const options = str.match(/\/.+\/(.*)/)[1]

  // Return compiled regex
  return new RegExp(main, options)
}

1

多亏了先前的回答,此块很好地用作了将可配置字符串应用于RegEx ..以过滤文本的通用解决方案:

var permittedChars = '^a-z0-9 _,.?!@+<>';
permittedChars = '[' + permittedChars + ']';

var flags = 'gi';
var strFilterRegEx = new RegExp(permittedChars, flags);

log.debug ('strFilterRegEx: ' + strFilterRegEx);

strVal = strVal.replace(strFilterRegEx, '');
// this replaces hard code solt:
// strVal = strVal.replace(/[^a-z0-9 _,.?!@+]/ig, '');

1

您可以使用复选框请求标志,然后执行以下操作:

var userInput = formInput;
var flags = '';
if(formGlobalCheckboxChecked) flags += 'g';
if(formCaseICheckboxChecked) flags += 'i';
var reg = new RegExp(userInput, flags);

看起来RegEx缺少尾随的p ..堆栈不会让我进行1个字符的编辑
Gene Bo

-3

eval用来解决这个问题。

例如:

    function regex_exec() {

        // Important! Like @Samuel Faure mentioned, Eval on user input is a crazy security risk, so before use this method, please take care of the security risk. 
        var regex = $("#regex").val();

        // eval()
        var patt = eval(userInput);

        $("#result").val(patt.exec($("#textContent").val()));
    }

3
在userInput上进行评估是一种疯狂的安全风险
塞缪尔·福雷

1
鲍比先生桌!
Luiz Felipe
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.