我可以在不抛出异常的情况下测试正则表达式在C#中是否有效

Mar*_*sen 46 c# regex

我允许用户输入正则表达式以匹配IP地址,以便在相关系统中进行IP过滤.我想验证输入的正则表达式是否有效,因为很多用户会弄乱op,尽管有良好的意图.

我当然可以在try/catch中做一个Regex.IsMatch(),看看它是否会爆炸,但有没有更智能的方法呢?速度不是一个问题,我只是宁愿避免无缘无故抛出异常.

Jef*_*ood 46

我认为在这种情况下例外是可以的.

这是我放在一起的东西:

private static bool IsValidRegex(string pattern)
{
    if (string.IsNullOrEmpty(pattern)) return false;

    try
    {
        Regex.Match("", pattern);
    }
    catch (ArgumentException)
    {
        return false;
    }

    return true;
}
Run Code Online (Sandbox Code Playgroud)

  • 我想知道 JIT 编译器会足够聪明还是足够愚蠢,因为不使用纯函数的返回值而优化掉整个 try catch 块? (2认同)
  • 只是`new Regex(pattern)`怎么样? (2认同)

Rob*_*ert 39

只要您捕获非常具体的异常,就可以执行try/catch.

如果使用正确,例外不是邪恶的.

  • 不幸的是,性能影响(特定于场景,我知道),以及异常类型非常普遍时调试的中断(ArgumentException对此很糟糕).我希望有一天能看到`Regex.TryParse()`引入.NET :) (29认同)
  • 该问题具体询问是否可以在不处理异常的情况下完成。 (5认同)
  • “如果使用得当,异常并不是邪恶的”,但抛出它们的成本很高,因为它们内部包含堆栈跟踪的转储。异常应该用于实际错误(理想情况下)而不是用于测试输入 (2认同)

Mar*_*ett 7

不是没有很多工作。正则表达式解析可能非常复杂,并且框架中没有任何公开内容来验证表达式。

System.Text.RegularExpressions.RegexNode.ScanRegex()看起来是负责解析表达式的主要函数,但它是内部的(无论如何都会抛出任何无效语法的异常)。因此,您需要重新实现解析功能——这在边缘情况或框架更新时无疑会失败。

我认为在这种情况下捕获 ArgumentException 是一个好主意。


Moh*_*MFa 5

我曾经使用过下面的功能并且没有任何问题。它同时使用异常和超时,但它是实用的。当然,它适用于 .Net Framework >= 4.5。

    public static bool IsValidRegexPattern(string pattern, string testText = "", int maxSecondTimeOut = 20)
    {
        if (string.IsNullOrEmpty(pattern)) return false;
        Regex re = new Regex(pattern, RegexOptions.None, new TimeSpan(0, 0, maxSecondTimeOut));
        try { re.IsMatch(testText); }
        catch{ return false; } //ArgumentException or RegexMatchTimeoutException
        return true;
    }
Run Code Online (Sandbox Code Playgroud)

  • 我现在改了。谢谢你,我的朋友。 (2认同)