regex不工作从word或Evernote复制的电子邮件地址



嗨,我有一个电子邮件字段的正则表达式,在大多数情况下工作良好,但在一个奇怪的情况下失败。以下是我使用的正则表达式

w+([-+.']w+)*@w+([-.]w+)*.w+([-.]w+)*

和以下是我正在测试正则表达式的两个相似的电子邮件地址。

global-do-not-reply@abc.com
global-​do-not-reply@abc.com

(不要与可见文本混淆,因为它们看起来是一样的)

奇怪的是,正则表达式在1个电子邮件地址上失败了。我发现的原因是,当我在Evernote中输入电子邮件地址(do-not-reply@abc.com)并按回车键时,它会变成一个链接。但是,如果您在电子邮件地址更改为链接后添加另一个文本(全局-),则新添加的文本将不被视为电子邮件地址的一部分。我在notepad++中检查了完整的电子邮件地址,发现Evernote (MS Word也一样)在电子邮件地址的开头添加了一个不可打印的字符,我后来添加到电子邮件地址的文本(在Evernote将文本更改为链接之后)出现在不可打印字符之前。这似乎就是原因。但我不确定如何使用正则表达式或使用任何其他方法来处理它。我正在研究ASP。净Webforms

在第二个示例中,-连字符后面有一个无法看到的多余字符。

最好使用这个正则表达式:

w+([-+.'].?w+)*@w+([-.]w+)*.w+([-.]w+)*

将考虑粘贴过程中出现的任何字符

demo here: http://regex101.com/r/bO9fJ4

或者作为一种替代方法,您可以在测试之前从电子邮件中删除所有不需要的字符。

在第一个'-'之后多一个U+200b字符(零加空格)。

我猜这是Evernote的方式,允许字符旁边的电子邮件地址(也可能是一个URL),这不是电子邮件的一部分。通过插入一个不可见的空格字符,它使"全局-"与电子邮件地址分开,就像用一个可视空间分隔一样。你的RegExp实际上是完全按照Evernote自己的电子邮件处理方式工作的,并且它识别相同的电子邮件地址。可以说,这是一个特性,而不是一个bug!

所以,一个解决方案是,你要确保印象笔记(或Word)对电子邮件地址的想法和你一样——确保"全局-"成为编辑器地址的一部分,而不仅仅是在视觉上与它相邻。

另一个解决方案是先删除U+200b字符

在验证前替换字符,例如

<asp:TextBox 
onchange="this.value=this.value.replace(/[^a-z0-9.-_@]+/gi, '')" ...

例子
<asp:TextBox ID="TextBox1" runat="server" />
<asp:RegularExpressionValidator ID="RegularExpressionValidator1"
    ControlToValidate="TextBox1"  
    ValidationExpression="w+([-+.']w+)*@w+([-.]w+)*.w+([-.]w+)*"
    EnableClientScript="true"
    ErrorMessage="Error"
    runat="server" />
<asp:TextBox ID="TextBox2" 
onkeyup="this.value=this.value.replace(/[^a-z0-9.-_@]+/gi, '')" 
runat="server"></asp:TextBox>
<asp:RegularExpressionValidator ID="RegularExpressionValidator2"
    ControlToValidate="TextBox2"  
    ValidationExpression="w+([-+.']w+)*@w+([-.]w+)*.w+([-.]w+)*"
    EnableClientScript="true"
    ErrorMessage="Error"
    runat="server" />

在两个文本框中复制并粘贴第二个电子邮件地址,并查看第二个文本框将以相同的模式匹配相同的文本

@smirnov让我找到了答案。尽管他提供的答案非常好,但它阻止了验证器控制器按预期工作。以下是以上问题的答案

    <asp:TextBox ID="txtEmail" CssClass="fieldMedium" runat="server" meta:resourcekey="txtEmail" 
     onkeyup="this.value=this.value.replace(/[-x1Fx7F-x9FxADu0378u0379u037F-u0383u038Bu038Du03A2u0528-u0530u0557u0558u0560u0588u058B-u058Eu0590u05C8-u05CFu05EB-u05EFu05F5-u0605u061Cu061Du06DDu070Eu070Fu074Bu074Cu07B2-u07BFu07FB-u07FFu082Eu082Fu083Fu085Cu085Du085F-u089Fu08A1u08AD-u08E3u08FFu0978u0980u0984u098Du098Eu0991u0992u09A9u09B1u09B3-u09B5u09BAu09BBu09C5u09C6u09C9u09CAu09CF-u09D6u09D8-u09DBu09DEu09E4u09E5u09FC-u0A00u0A04u0A0B-u0A0Eu0A11u0A12u0A29u0A31u0A34u0A37u0A3Au0A3Bu0A3Du0A43-u0A46u0A49u0A4Au0A4E-u0A50u0A52-u0A58u0A5Du0A5F-u0A65u0A76-u0A80u0A84u0A8Eu0A92u0AA9u0AB1u0AB4u0ABAu0ABBu0AC6u0ACAu0ACEu0ACFu0AD1-u0ADFu0AE4u0AE5u0AF2-u0B00u0B04u0B0Du0B0Eu0B11u0B12u0B29u0B31u0B34u0B3Au0B3Bu0B45u0B46u0B49u0B4Au0B4E-u0B55u0B58-u0B5Bu0B5Eu0B64u0B65u0B78-u0B81u0B84u0B8B-u0B8Du0B91u0B96-u0B98u0B9Bu0B9Du0BA0-u0BA2u0BA5-u0BA7u0BAB-u0BADu0BBA-u0BBDu0BC3-u0BC5u0BC9u0BCEu0BCFu0BD1-u0BD6u0BD8-u0BE5u0BFB-u0C00u0C04u0C0Du0C11u0C29u0C34u0C3A-u0C3Cu0C45u0C49u0C4E-u0C54u0C57u0C5A-u0C5Fu0C64u0C65u0C70-u0C77u0C80u0C81u0C84u0C8Du0C91u0CA9u0CB4u0CBAu0CBBu0CC5u0CC9u0CCE-u0CD4u0CD7-u0CDDu0CDFu0CE4u0CE5u0CF0u0CF3-u0D01u0D04u0D0Du0D11u0D3Bu0D3Cu0D45u0D49u0D4F-u0D56u0D58-u0D5Fu0D64u0D65u0D76-u0D78u0D80u0D81u0D84u0D97-u0D99u0DB2u0DBCu0DBEu0DBFu0DC7-u0DC9u0DCB-u0DCEu0DD5u0DD7u0DE0-u0DF1u0DF5-u0E00u0E3B-u0E3Eu0E5C-u0E80u0E83u0E85u0E86u0E89u0E8Bu0E8Cu0E8E-u0E93u0E98u0EA0u0EA4u0EA6u0EA8u0EA9u0EACu0EBAu0EBEu0EBFu0EC5u0EC7u0ECEu0ECFu0EDAu0EDBu0EE0-u0EFFu0F48u0F6D-u0F70u0F98u0FBDu0FCDu0FDB-u0FFFu10C6u10C8-u10CCu10CEu10CFu1249u124Eu124Fu1257u1259u125Eu125Fu1289u128Eu128Fu12B1u12B6u12B7u12BFu12C1u12C6u12C7u12D7u1311u1316u1317u135Bu135Cu137D-u137Fu139A-u139Fu13F5-u13FFu169D-u169Fu16F1-u16FFu170Du1715-u171Fu1737-u173Fu1754-u175Fu176Du1771u1774-u177Fu17DEu17DFu17EA-u17EFu17FA-u17FFu180Fu181A-u181Fu1878-u187Fu18AB-u18AFu18F6-u18FFu191D-u191Fu192C-u192Fu193C-u193Fu1941-u1943u196Eu196Fu1975-u197Fu19AC-u19AFu19CA-u19CFu19DB-u19DDu1A1Cu1A1Du1A5Fu1A7Du1A7Eu1A8A-u1A8Fu1A9A-u1A9Fu1AAE-u1AFFu1B4C-u1B4Fu1B7D-u1B7Fu1BF4-u1BFBu1C38-u1C3Au1C4A-u1C4Cu1C80-u1CBFu1CC8-u1CCFu1CF7-u1CFFu1DE7-u1DFBu1F16u1F17u1F1Eu1F1Fu1F46u1F47u1F4Eu1F4Fu1F58u1F5Au1F5Cu1F5Eu1F7Eu1F7Fu1FB5u1FC5u1FD4u1FD5u1FDCu1FF0u1FF1u1FF5u1FFFu200B-u200Fu202A-u202Eu2060-u206Fu2072u2073u208Fu209D-u209Fu20BB-u20CFu20F1-u20FFu218A-u218Fu23F4-u23FFu2427-u243Fu244B-u245Fu2700u2B4D-u2B4Fu2B5A-u2BFFu2C2Fu2C5Fu2CF4-u2CF8u2D26u2D28-u2D2Cu2D2Eu2D2Fu2D68-u2D6Eu2D71-u2D7Eu2D97-u2D9Fu2DA7u2DAFu2DB7u2DBFu2DC7u2DCFu2DD7u2DDFu2E3C-u2E7Fu2E9Au2EF4-u2EFFu2FD6-u2FEFu2FFC-u2FFFu3040u3097u3098u3100-u3104u312E-u3130u318Fu31BB-u31BFu31E4-u31EFu321Fu32FFu4DB6-u4DBFu9FCD-u9FFFuA48D-uA48FuA4C7-uA4CFuA62C-uA63FuA698-uA69EuA6F8-uA6FFuA78FuA794-uA79FuA7AB-uA7F7uA82C-uA82FuA83A-uA83FuA878-uA87FuA8C5-uA8CDuA8DA-uA8DFuA8FC-uA8FFuA954-uA95EuA97D-uA97FuA9CEuA9DA-uA9DDuA9E0-uA9FFuAA37-uAA3FuAA4EuAA4FuAA5AuAA5BuAA7C-uAA7FuAAC3-uAADAuAAF7-uAB00uAB07uAB08uAB0FuAB10uAB17-uAB1FuAB27uAB2F-uABBFuABEEuABEFuABFA-uABFFuD7A4-uD7AFuD7C7-uD7CAuD7FC-uF8FFuFA6EuFA6FuFADA-uFAFFuFB07-uFB12uFB18-uFB1CuFB37uFB3DuFB3FuFB42uFB45uFBC2-uFBD2uFD40-uFD4FuFD90uFD91uFDC8-uFDEFuFDFEuFDFFuFE1A-uFE1FuFE27-uFE2FuFE53uFE67uFE6C-uFE6FuFE75uFEFD-uFF00uFFBF-uFFC1uFFC8uFFC9uFFD0uFFD1uFFD8uFFD9uFFDD-uFFDFuFFE7uFFEF-uFFFBuFFFEuFFFF]/g, '')" />

我查看了下面的链接,以获得所有不可打印的Unicode字符的列表。

如何替换不可打印的unicode字符(Javascript)

现在,上面的解决方案将不会干扰正则表达式验证器的功能,并且不可打印的字符也将从文本中删除。

感谢所有人的帮助。

试着用这个表达式,这对我来说很好:

Regex regex = new Regex(@"^([w.-]+)@([w-]+)((.(w){2,3})+)$");

最新更新