-3

如果文本框的内容似乎不是有效的电子邮件地址,我会尝试禁止用户输入。这不是在用户键入并离开文本框后进行的检查,它会在用户键入时正确检查,如果文本看起来将是无效的电子邮件地址,则禁止输入。例如,当用户输入“ilove.net”时,这被称为有效电子邮件地址的第一部分(因此目前一切正常),现在如果用户再次输入“@”,文本仍然可以对于电子邮件地址的第一部分。但是,如果用户接下来输入“@”,则无论用户在第二个“@”之后输入什么,这将被识别为无效的电子邮件地址,因此输入将被禁止。

这是我的第一次尝试:

RegEx regEx = new RegEx(@"^(?!(\d|\s|-|[.]))([^.-]*[.]?[^. -]+)+@([^-. ]+[.][^-. ]+)+(?<=\D)$");
string basicSampleEmailAddress = "xxx@x.x";
private void textEmail_KeyPress(object sender, KeyPressEventArgs e){
    string current = textBoxEmail.Text.Insert(textBoxEmail.SelectionStart,e.KeyChar.ToString());
    bool matchable = false;
    for(int i = basicSampleEmailAddress.Length-1; i >= 0; i--){
        if(regEx.IsMatch(string.Format("{0}{1}",current,basicSampleEmailAddress.Substring(i))) { matchable=true; break;}
    }
    e.Handled = !matchable;
}

当我在 textEmail(TextBox)中输入前 5-7 个字符时,这似乎工作正常,但是当我输入下一个字符时可以看到“处理缓慢”,即使我输入速度很快,我的应用程序也会冻结处理某些东西(我认为它与 RegEx 相关),CPU 使用率约为 20%,并且表单标题附加了文本“未响应”。事实上,一旦变成这样的冰冻状态,我就无法让它正常了。我必须通过 VS Studio 停止应用程序。

现在,我尝试了另一个表达式,一切正常: 代码与上面的代码相同,只是我将正则表达式更改为这个:

regEx = new Regex(@"(?i)^[0-9a-z_]{3,}((\.[0-9a-z]+)+)?@[a-z]+(\.[a-z0-9]+)+$");

这意味着,问题是由第一次尝试中的表达式引起的。我想知道为什么使用第一个表达式时速度太慢?自从我知道 RegEx 并爱上它的那一天起,我就觉得 RegEx 是一个非常快的东西,速度几乎取决于输入的字符串,而不太取决于表达式。

您的帮助将不胜感激!

4

1 回答 1

2

问题是由这部分([^.-]*[.]?[^. -]+)+(在@标志之前)引起的。给定一个输入,在回溯期间something@invalid--gar..bage有多种方法something@invalid可以适应子模式。([^.-]*[.]?[^. -]+)+这里没有什么令人惊讶的。由于[^. -]+can match @,引擎只会向前移动,然后再返回。

下面显示了从失败的匹配回溯something@invalid时匹配的成功尝试:([^.-]*[.]?[^. -]+)+

(something@invali [empty] d)
(something@inval [empty] id)
(something@inval [empty] i) ([empty] [empty] d)
(something@inva [empty] lid)
(something@inva [empty] li) ([empty] [empty] d)
(something@inva [empty] l) (i [empty] d)
(something@inva [empty] l) ([empty] [empty] id)
(something@inva [empty] l) ([empty] [empty] i) ([empty] [empty] d)
(something@inv [empty] alid)
...

()是每次迭代的文本匹配([^.-]*[.]?[^. -]+)+,里面的3部分()对应于匹配的文本[^.-]*[.]?[^. -]+

如您所见,引擎在这里做了无用的回溯工作。问题是当没有匹配时,您允许引擎回溯的方式太多。请注意:

  • [^.-]*[.]?[^. -]+可以提供n重试与 length 匹配的子字符串的方法n

    例如:(something@invali [empty] d), (something@inval [empty] id), (something@inva [empty] lid), ...

  • 整个事情被重复的事实并没有帮助,因为你有 2 n种方法可以将长度为 n 的匹配子字符串拆分为重复。

    例如:

    • 1组:(something@invalid)
    • 2组:(something@inval) (id)(something@invali) (d)(someth) (ing@invalid)
于 2013-05-12T04:20:33.997 回答