如何检查输入的字符串是否是有效的正则表达式?

87

在JavaScript中,如何检查字符串是否是一个合适的正则表达式并能编译?

例如,当您执行以下JavaScript代码时,它会产生一个错误。

var regex = new RegExp('abc ([a-z]+) ([a-z]+))');
// produces:
// Uncaught SyntaxError: Invalid regular expression: /abc ([a-z]+) ([a-z]+))/: Unmatched ')'

如何确定一个字符串是否为有效的正则表达式?


11
你需要一个正则表达式来测试另一个正则表达式?哈哈。 - Niccolò Campolungo
请明确说明您的代码,我们将会帮助您。 - Ganesh Rengarajan
1
我想检查输入的字符串是否是有效的正则表达式。 - Jak Samun
41
为什么这个问题被标记为“不是一个真正的问题”或者“关闭了”? 或者受到了负面反馈?我在这里找到了答案,正好解决了我遇到的问题! - Florian Mertens
3
除非被编辑过,否则这个问题并没有什么含糊不清的地方——有效的表达式是那些可以编译的。既然我们在谈论 JavaScript,那么假设这意味着 ES 表达式是有意义的。 - riv
显示剩余8条评论
6个回答

119

您可以使用 try/catchRegExp 构造函数:

var isValid = true;
try {
    new RegExp("the_regex_to_test_goes_here");
} catch(e) {
    isValid = false;
}

if(!isValid) alert("Invalid regular expression");

2
@Jak:如果您提供更多关于“不起作用”的具体信息,那么我们可能能够帮助您。但仅仅说“它不起作用”并没有给我们任何信息。您尝试了什么输入?您得到了什么输出?您是否遇到了其他错误? - Felix Kling
4
@DmitryDavydov 所使用的正则表达式在技术上确实是“正确”的,尽管它非常令人困惑。请注意,你引用的行为是POSIX标准特殊字符...在方括号表达式中将失去其特殊含义)。 - Jon
3
Chrome 63 中无法运行 - 构造函数似乎可以接受任何值而不抛出异常。 - twoflower
@twoflower 这是不可能的,因为我相当确定 Chrome 仍然遵守规范;而且规范说,如果正则表达式模式无效,必须抛出 SyntaxError...也许你使用的模式实际上是正确的? - Jon
@Jon 你说得对,我的表达还不够混乱 :-) - twoflower
显示剩余9条评论

4
这里有一个小函数,可以检查正则表达式的有效性,包括字符串和模式两种类型:
function validateRegex(pattern) {
    var parts = pattern.split('/'),
        regex = pattern,
        options = "";
    if (parts.length > 1) {
        regex = parts[1];
        options = parts[2];
    }
    try {
        new RegExp(regex, options);
        return true;
    }
    catch(e) {
        return false;
    }
}

用户将能够测试test/test/g等内容,例如。这里是一个有效的演示Here

1
此函数允许任意字符串,因此我不确定它是否符合操作者的要求。 - simon-p-r
我的答案和另一个答案基本上做了完全相同的事情,唯一的区别是我还考虑了模式内可能存在的选项。而且,老实说,OP想要的只是“检查输入字符串是否为有效的正则表达式”,没有特别指定输入长度的限制,因此可以将任何字符串作为输入传递。此外,我正在按照他的要求做,甚至返回适当的 true 或 false 值。 - Niccolò Campolungo
9
你没有考虑到正则表达式中包含“/”字符的情况。 - Johanneke

1

这里的回答都不能满足我检查字符串是否为其他语言(主要是PHP)有效正则表达式的需求,因为它们要么忽略标志、分隔符或转义特殊字符,所以我自己编写了一个函数。

function isValidRegex(s) {
  try {
    const m = s.match(/^([/~@;%#'])(.*?)\1([gimsuy]*)$/);
    return m ? !!new RegExp(m[2],m[3])
        : false;
  } catch (e) {
    return false
  }
}

console.log(isValidRegex('abc')) //False
console.log(isValidRegex('/abc/')) //True
console.log(isValidRegex('/ab#\/[c]/ig')) //True
console.log(isValidRegex('@ab#\/[c]@ig')) //Special delimiters: True
console.log(isValidRegex('/ab\/[c/ig')) //False
console.log(isValidRegex('/abc/gig')) //False

您可以使用此函数将字符串转换为 RegExp 对象。

function stringToRegex(s) {
   const m = s.match(/^([/~@;%#'])(.*?)\1([gimsuy]*)$/);
   return m ? new RegExp(m[2], m[3]) : new RegExp(s);
}

console.log(stringToRegex('abc'))
console.log(stringToRegex('/abc/'))
console.log(stringToRegex('/ab#\/[c]/ig'))
console.log(stringToRegex('@ab#\/[c]@ig'))
try {
  console.log(stringToRegex('/ab#\/[c/ig'))
} catch (e) {
  console.log('Not a valid regex')
}


0

这个函数可以将'/'字符作为正则表达式中的普通字符处理,并在字符串中考虑转义。它总是返回一个正则表达式,如果不是一个好的正则表达式字符串,则返回null。

function getRegex(regex) {
    try {
        regex = regex.trim();
        let parts = regex.split('/');
        if(regex[0] !== '/' || parts.length< 3){
          regex = regex.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); //escap common string
          return new RegExp(regex);
        }

        const option =parts[parts.length - 1];
        const lastIndex = regex.lastIndexOf('/');
        regex = regex.substring(1, lastIndex);
        return new RegExp(regex, option);
    } catch (e) {
        return null
    }
}

console.log(getRegex('ab/c'))
let htmlStartTag = getRegex('/<(?!/)(?!br)(.+?)(?<!/)>/mgs');
console.log(htmlStartTag)
let result = `</button><input id="warehouse-search-field-tablet"
class="form-control search-field"
 title="Warehouse Search Field" name="location" type="search" value="">content`.matchAll(htmlStartTag);
 console.log([...result])


-1
function isRegExp(regExp){
          try {
                new RegExp(regExp);
              } catch(e) {
                return false
              }
         return true
    }

ex:
isRegExp(/@(\w+)/g) = true

4
你能否对你贴出的代码做一些解释呢?“简洁明了是可以接受的,但更充分的解释会更好。”- 我该如何撰写出色的回答? - ejderuby
我在这里只是一个初学者,我会用更易懂的解释来改进我的答案。为此,所有实验代码都是离线的,让我将所有代码推送到Github上,并在这里回复参考链接。谢谢 #HappyCoding - Rahul Shahare
5
这基本上是2013年原回答的重复。 - SwissCoder

-3
问题已经解决,但如果有人需要定义字符串是否为有效的RegExp或根本不是RegExp,可以使用new Function()和函数体内的模板以及前面提到的try ... catchnew RegExp()
以下是带有说明的代码片段:

const isRegExp = (string) => {
    try {
        return new Function(`
            "use strict";
            try {
                new RegExp(${string});
                return true;
            } catch (e) {
                return false;
            }
        `)();
    } catch(e) {
        return false;
    }
};

// Here the argument 'simplyString' shall be undefined inside of the function
// Function(...) catches the error and returns false
console.log('Is RegExp valid:', isRegExp('simplyString'));

// Here the argument shall cause a syntax error
// isRegExp function catches the error and returns false
console.log('Is RegExp valid:', isRegExp('string which is not a valid regexp'));

// Here the argument is not a valid RegExp, new RegExp(...) throws an error
// Function(...) catches the error and returns false
console.log('Is RegExp valid:', isRegExp('abc ([a-z]+) ([a-z]+))'));

// Valid RegExp, passed as a string
console.log('Is RegExp valid:', isRegExp('/^[^<>()[\]\\.,;:\s@\"]$/'));

// Valid RegExp, passed as a RegExp object
console.log('Is RegExp valid:', isRegExp(/^[^<>()[\]\\.,;:\s@\"]$/));

// Howewer, the code injection is possible here
console.log('Is RegExp valid:', isRegExp(');console.log("This is running inside of the Function(...) as well"'));


3
一个带有代码注入漏洞的答案获得了两个赞。 - JeremyP
1
一篇关于DailyWTF的文章充分指出了这个答案存在的问题:https://thedailywtf.com/articles/evaluating-regexes - Joshua Voskamp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接