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

Gor*_*son 315 html javascript regex

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

我的问题是从用户获取字符串并将其转换为正则表达式.如果我说他们不需要//围绕他们进入的正则表达式,那么他们就不能设置标志,比如gi.所以他们必须有//表达式,但是如何将该字符串转换为正则表达式?它不能是一个文字,因为它是一个字符串,我不能将它传递给RegExp构造函数,因为它不是没有字符串的字符串//.有没有其他方法可以将用户输入字符串转换为正则表达式?我是否必须用//'s 解析正则表达式的字符串和标志然后以另一种方式构造它?我应该让他们输入一个字符串,然后单独输入标志吗?

Gum*_*mbo 582

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

var re = new RegExp("a|b", "i");
// same as
var re = /a|b/i;
Run Code Online (Sandbox Code Playgroud)

  • 当这样做时,你必须转义反斜杠,例如`var re = new RegExp("\\ w +");` (52认同)
  • @holms [regex101.com](https://regex101.com/)也是一款出色的正则表达式在线工具 (11认同)
  • 我花了一段时间才看到不需要尾部斜杠 (2认同)
  • @JDSmith 在你的例子中我不是这个意思。我的意思是,如果您希望双引号成为硬编码的正则表达式的一部分,则需要转义双引号。显然,如果字符串位于一个变量中,例如来自 `<input>` HTML 标签,则这些都不适用。`var re = new RegExp("\"\\w+\"");` 是一个硬编码正则表达式的例子,它使用 RegExp 构造函数和必要的双引号 __is__ 转义。我所说的变量中的字符串的意思是你可以只做 `var re = new RegExp(str);` 并且 `str` 可以包含双引号或反斜杠,没有问题。 (2认同)

Ano*_*ous 65

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

要么

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

  • 或者让RegExp构造函数失败,"在正则表达式中尾随\",而不是编写复杂的解析器. (6认同)

Riv*_*all 15

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

我是从escape-string-regexp NPM模块获得的.

尝试一下:

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

console.log(new RegExp(escapeStringRegExp('example.com')));
// => /example\.com/
Run Code Online (Sandbox Code Playgroud)

  • 这似乎与问题所问的相反。它希望像正则表达式一样对待字符串,因此用户可以提供像“/.*\.com$/”这样的输入,并使其与“example.com”匹配 (2认同)

Aym*_*ieh 14

使用JavaScript RegExp对象构造函数.

var re = new RegExp("\\w+");
re.test("hello");
Run Code Online (Sandbox Code Playgroud)

您可以将标志作为第二个字符串参数传递给构造函数.有关详细信息,请参阅文档


sta*_*abm 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);
}
Run Code Online (Sandbox Code Playgroud)

  • 你总是可以使用`.split()`函数而不是长正则表达式字符串.`regParts = inputstring.split('/')`这会使`regParts [1]`为正则表达式字符串,`regParts [2]`为分隔符(假设正则表达式的设置为`/.../ gim` ).您可以检查是否存在带有`regParts [2] .length <0`的分隔符. (2认同)

Ric*_*all 6

尝试使用以下函数:

const stringToRegex = str => {
    // Main regex
    const main = str.match(/\/(.+)\/.*/)[1]
    
    // Regex options
    const options = str.match(/\/.+\/(.*)/)[1]
    
    // Compiled regex
    return new RegExp(main, options)
}
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它:

"abc".match(stringToRegex("/a/g"))
//=> ["a"]
Run Code Online (Sandbox Code Playgroud)


Tof*_*del 6

这是我的单行函数,用于处理自定义分隔符和无效标志

// One liner
var stringToRegex = (s, m) => (m = s.match(/^([\/~@;%#'])(.*?)\1([gimsuy]*)$/)) ? new RegExp(m[2], m[3].split('').filter((i, p, s) => s.indexOf(i) === p).join('')) : new RegExp(s);

// Readable version
function stringToRegex(str) {
  const match = str.match(/^([\/~@;%#'])(.*?)\1([gimsuy]*)$/);
  return match ? 
    new RegExp(
      match[2],
      match[3]
        // Filter redundant flags, to avoid exceptions
        .split('')
        .filter((char, pos, flagArr) => flagArr.indexOf(char) === pos)
        .join('')
    ) 
    : new RegExp(str);
}

console.log(stringToRegex('/(foo)?\/bar/i'));
console.log(stringToRegex('#(foo)?\/bar##gi')); //Custom delimiters
console.log(stringToRegex('#(foo)?\/bar##gig')); //Duplicate flags are filtered out
console.log(stringToRegex('/(foo)?\/bar')); // Treated as string
console.log(stringToRegex('gig')); // Treated as string
Run Code Online (Sandbox Code Playgroud)

  • 仅仅因为您将 10 条语句塞进一行,它就不是一行了:) (5认同)
  • 10 条陈述?它只是一个三元表达式,如果它是一行,那么它就是一个行;)如果你说它是 3 行,因为该函数只是为了可读性,否则你可以执行 `const stringToRegex = (s, m) =&gt; (m = s.match(/^([\/~@;%#'])(.*?)\1([gimsuy]*)$/)) ? new RegExp(m[2], m[3].split('').filter((i, p, s) =&gt; s.indexOf(i) === p).join('')) : new正则表达式;` (2认同)