以下是我的代码的摘录:
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在处理最后一行时挂起。我做了一些实验,但仍然无法理解为什么它在线路末端没有匹配时挂起。请帮忙!
答案 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
循环之外。
你在循环的第一次迭代结束时阻塞线程,等待用户输入。