使用正则表达式在C++中进行国际电子邮件验证

4

我在验证国际邮件地址时遇到了一些问题,例如john.doe@神谕.comsara.smith@神谕.combabu.ratnakar+आଆఉఊګ神谕@gmail.comtestæœö.神谕#$&*éùôß@äßæçëêùé+आଆ神谕.com。我想用C ++中的REGEX解决这个问题,并使内容更加通俗易懂。以下是在Java中工作正常的正则表达式:

^[\\p{L}0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\p{L}0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\p{L}0-9](?:[\\p{L}0-9-]*[\\p{L}0-9])?\\.)+[\\p{L}0-9](?:[\\p{L}0-9-]*[\\p{L}0-9])?$

我尝试在C++中进行轻微修改后使用相同的方法

std::string str("[\\\\p{L}0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[\\\\p{L}0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\\\p{L}0-9](?:[\\\\p{L}0-9-]*[\\\\p{L}0-9])?\.)+[\\\\p{L}0-9](?:[\\\\p{L}0-9-]*[\\\\p{L}0-9])?"); 

std::regex rx4(str);

但是regex_match在所有情况下都失败了。我认为问题出在\p{L}上。当我将其替换为a-z时,它接受带有英文字母的电子邮件地址。也就是说,这个可以工作:

std::regex rx3("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", std::regex::ECMAScript);

/p{L}在C++中不能匹配Unicode字符吗?


2
你在构建正则表达式字符串时是否正确使用了转义符 (\\)? - πάντα ῥεῖ
3
简短回答:不要(使用复杂的正则表达式验证电子邮件地址)。或者至少不要过度努力。你仍然需要发送验证电子邮件,所以只需使用简单的正则表达式,然后尝试向他们发送电子邮件即可。 - BoBTFish
是的,我相信转义是正确的。我只需要在“\p{L}”之前再加两个正斜杠“\”即可。 - vijin
1
正如指出的那样 - 转义。Java和C++以相同的方式进行转义,因此\应该保持不变,而不是\\。 - SamWhan
当我只保留两个斜杠即 \p{L} 时,会出现以下错误:Microsoft C++ exception: std::tr1::regex_error at memory location 0x047fcbfc。 - vijin
1
жҲ‘жғізҹҘйҒ“ "^(?:(?:[^<>()\\[\\].,;:\\s@\"]+(?:\\.[^<>()\\[\\].,;:\\s@\"]+)*)|\".+\")@(?:(?:[^<>()\\[\\].,;:\\s@\"]+\\.)+[^<>()\\[\\].,;:\\s@\"]{2,})$" жҳҜеҗҰйҖӮз”ЁдәҺжӮЁгҖӮе®ғеңЁ иҝҷйҮҢ еҸ‘еёғгҖӮ - Wiktor Stribiżew
1个回答

4

C++ std::regex 支持6种正则表达式语法:

std::regex_constants 定义了六种不同的正则表达式语法:

ECMAScript: 类似于 JavaScript
basic: 类似于 POSIX BRE。
extended: 类似于 POSIX ERE。
grep: 与 basic 相同,但增加了将换行符视为交替运算符的功能。
egrep: 与 extended 相同,但增加了将换行符视为交替运算符的功能。
awk: 与 extended 相同,但增加了支持非可打印字符的常见转义符的功能。

这些语法都不支持Unicode 属性(或Unicode 类别类)例如 \p{L},因此您不能在模式中使用 \p{L}

如果您的解决方法适用,请使用它:

std::regex rx3("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", std::regex::ECMAScript);

或者从已知的在JavaScript中验证电子邮件地址?SO帖子中获取一个版本(删除锚点,因为您正在使用regex_match并重新转义以用于非原始字符串文字,以及std::regex :: ECMAScript ,因为它是默认使用的):
std::regex rx3("(?:(?:[^<>()\\[\\].,;:\\s@\"]+(?:\\.[^<>()\\[\\].,;:\\s@\"]+)*)|\".+\")@(?:(?:[^<>()‌​\\[\\].,;:\\s@\"]+\\.)+[^<>()\\[\\].,;:\\s@\"]{2,})")

我尝试了你的建议,但仍然遇到一些问题。我已经在Java和C++中都使用了正则表达式。但是电子邮件地址“伊昭傑@郵件.商務”在Java中被接受,但在C++中被拒绝。在Java中使用的正则表达式是:“^(?:(?:[^<>()\[\].,;:\s@"]+(?:\.[^<>()\[\].,;:\s@"]+))|".+")@(?:(?:[^<>()‌​\[\].,;:\s@"]+\.)+[^<>()\[\].,;:\s@"]{2,})$”。在C++中使用的是“std::regex rx3("(?:(?:[^<>()\[\].,;:\s@"]+(?:\.[^<>()\[\].,;:\s@"]+))|".+")@(?:(?:[^<>()‌​\[\].,;:\s@"]+\.)+[^<>()\[\].,;:\s@"]{2,})")”。 - vijin
使用^\S+@[^\s@]+\.[^\s@.]+$,为什么要这么限制电子邮件? - Wiktor Stribiżew
是的,我明白。但是我试图理解这里的差异。行为应该在Java和CPP中相同,对吧? - vijin
在C++中是否有与\p{L}等效的内容? - vijin
1
使用 Boost 正则表达式库或 PCRE、PCRE2,它们支持 Unicode 类别。顺便说一下,std::regex reg(R"((?:(?:[^<>()\[\].,;:\s@\"]+(?:\.[^<>()\[\].,;:\s@\"]+)*)|\".+\")@(?:(?:[^<>()\[\].,;:\s@\"]+\.)+[^<>()\[\].,;:\s@\"]{2,}))"); 可以匹配您的电子邮件。请参阅 https://ideone.com/d26xH2。 - Wiktor Stribiżew
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接