RegularExpressions.Regex.IsMatch正在挂起

时间:2013-12-26 02:48:08

标签: c# regex

以下是我的代码的摘录:

string[] myStr =
        { 
           " Line1:  active 56:09 -  tst0063, tst0063",
           "Contacts accosiated with line 1 -   tst0063, tst0063",
           "Line 1: 00:00:32      Wrap: 00:00:20 - tst0063, tst0063",
           "Line 1: 00:00:17      Active: 00:00:15 - tst0064, tst0064"
        };

string sPattern = @"^Line(\s*\S*)*tst0063$";
RegexOptions options = RegexOptions.IgnoreCase;

foreach (string s in myStr)
{
    System.Console.Write(s);

    if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern, options))
    {
        System.Console.WriteLine(" - valid");
    }
    else
    {
        System.Console.WriteLine(" - invalid");
    }
    System.Console.ReadLine();
}

RegularExpressions.Regex.IsMatch在处理最后一行时挂起。我做了一些实验,但仍然无法理解为什么它在线路末端没有匹配时挂起。请帮忙!

2 个答案:

答案 0 :(得分:3)

问题不在于为什么第四次测试会挂起,而是为什么前三次没有。第一个字符串以空格开头,第二个字符串以Contacts开头,两者都不匹配正则表达式^Line,因此前两个匹配尝试立即失败。第三个字符串匹配正则表达式;虽然它需要的时间比它应该的长(因为我将要解释的原因),但它似乎仍然是瞬间的。

第四个匹配失败,因为字符串与正则表达式的结尾部分不匹配:tst0063$。当失败时,正则表达式引擎会备份到正则表达式(\s*\S*)*的变量部分,并开始尝试所有不同的方式将其放到字符串上。与第三个字符串不同,这次它必须尝试零个或多个空白字符(\s*)的每个可能组合,后跟零个或多个非空格字符(\S*),零次或多次,在它放弃之前。可能性不是无限的,但它们也可能是。

您可能正在考虑[\s\S]*,这是一个众所周知的习惯用于匹配任何字符,包括换行符。它在JavaScript中使用,它没有办法使点(.)匹配行分隔符。大多数其他风格允许您指定更改点的行为的匹配模式;有些人称之为 DOTALL 模式,但.NET使用更常见的单行

string sPattern = @"^Line.*tst0063$";
RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Singleline;

您还可以使用内嵌修饰符:

string sPattern = @"(?is)^Line.*tst0063$";

更新:在回复您的评论时,是的,正则表达式引擎无法判断任何匹配必须tst0063结尾似乎有些奇怪。但它并不总是那么容易辨别。它应该花多少努力寻找这样的捷径?在所有匹配(成功和失败)之前,您可以使用多少快捷键进入常规匹配算法?

.NET拥有最好的正则表达式实现之一:快速,强大,并具有一些真正令人惊叹的功能。但你必须考虑你要告诉它做什么。例如,如果您知道必须至少有一个内容,请使用+,而不是*。如果您遵循该规则,则不会遇到此问题。这个正则表达式:

@"^Line(\s+\S+)*tst0063$"

......工作正常。 (\s+\S+)*是匹配零个或多个单词的完全合理的方式,其中单词被定义为一个或多个非空白字符,通过一个或多个空白字符与其他单词分隔。 (那是你想要做的吗?)

答案 1 :(得分:2)

System.Console.ReadLine();移到foreach循环之外。

你在循环的第一次迭代结束时阻塞线程,等待用户输入。