使用正则表达式发送电子邮件的最小和最大长度有限,但错误

时间:2015-12-24 02:09:16

标签: c regex posix

以下正则表达式是否有任何错误:

^(?=.{1,32}$)\w+([-+.]\w+)*@\w+([-+.]\w+)*.\w+([-+.]\w+)*$

我使用此正则表达式模式来检查电子邮件格式和长度,但执行时出现以下错误消息:

  

无效使用重复运算符,例如使用'*'作为第一个字符。

我尝试在我的正则表达式前面使用\来转义?regcomp()可以编译成功,但结果是错误的。

这是我的支票字符串:

  

test.test@test.com - >失败,错误的结果

     

测试:test@test.com - >失败,正确的结果

环境

  

操作系统:

     

Linux debian8 3.16.0-4-686-pae#1 SMP Debian   3.16.7-ckt11-1 + deb8u5(2015-10-09)i686 GNU / Linux

     

GCC

     

使用内置规格。 COLLECT_GCC = GCC   COLLECT_LTO_WRAPPER = / usr / lib中/ GCC / i586的-Linux的GNU / 4.9 / LTO-包装   目标:i586-linux-gnu配置为:../ src / configure -v   --with-pkgversion ='Debian 4.9.2-10'--with-bugurl = file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages = c,c ++,java, go,d,fortran,objc,obj-c ++ --prefix = / usr --program-suffix = -4.9 --enable-shared --enable-linker-build-id --libexecdir = / usr / lib --without -included-gettext --enable-threads = posix --with-gxx-include-dir = / usr / include / c ++ / 4.9 --libdir = / usr / lib --enable-nls --with-sysroot = / - -enable-clocale = gnu --enable-libstdcxx-debug --enable-libstdcxx-time = yes --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt = gtk --enable-gtk-cairo --with-java-home = / usr / lib / jvm / java-1.5.0-gcj-4.9-i386 / jre --enable-java-home --with-jvm-root-dir = / usr / lib / jvm / java-1.5.0-gcj-4.9-i386 --with-jvm-jar-dir = / usr / lib /jvm-exports/java-1.5.0-gcj-4.9-i386 --with-arch-directory = i386 --with-ecj-jar = / usr / share / java / eclipse-ecj.jar --enable-objc -gc --enable-targets = all --enable-multiarch --with-arch-32 = i586 --with-multilib-list = m32,m64,mx32 - enable-multilib --with-tune = generic --enable-checking = release --build = i586-linux-gnu --host = i586-linux-gnu --target = i586-linux-gnu线程模型:posix gcc版本4.9.2(Debian 4.9.2-10)

2 个答案:

答案 0 :(得分:1)

根据你的标签和使用regcomp的提示,我假设你使用标准的Posix库regcompregexec函数来进行正则表达式匹配

regcomp使用的正则表达式语法完全记录在man 7 regex(或Posix itself中,我发现稍微更具可读性)。其他语言中有许多正则表达式库可以实现更多种类的正则表达式语法,但是您没有使用其他语言。因此,如果您使用的语法不在这些文档中,则它将无效。这包括:

  • 转发前瞻性断言,例如(?=.{1,32}$)。实际上,没有外观断言,也没有任何其他语法从(?开始。
  • 使用\w表示字母数字字符。如果你使用扩展正则表达式(通过提供REG_EXTENDED作为regcomp的第三个参数 - 你应该总是做),那么\确实阻止了下面的正则表达式操作符具有特殊含义。但是,Gnu实现确实提供了一些扩展。它处理反向引用,即使Posix仅在基本正则表达式中定义它们。有些版本会处理\w和朋友,但这可能不适用于其他Posix正则表达式实现,例如Mac OS X.

您可以使用Posix字符类来获得\w\W\s等效果。例如,单词字符(\w)可以写为字符类[_[:alnum:]],而非空格字符(\S)可以写为[^[:space:]]。使用此语法是完全可移植的。

前瞻断言没有解决方法,除了创建一个单独的正则表达式并匹配它,从正确的点开始。但是如果你只是想检查字符串的长度,你不需要任何复杂的东西。只需检查字符串的长度:

size_t len = strnlen(str, maxlen + 1);
if (len >= minlen && len <= maxlen &&
    regexec(&preg, str, 0, 0, 0)) {
  /* The string matched, and its length is between minlen and maxlen */
} else {
  /* Not a match, or too short or too long */
}

(我使用了strnlen,它位于Posix 2008中;它是在glibc中实现的。优点是,如果你只需要知道字符串不是太长,strnlen也可以避免查看很多字符。也就是说,如果我要拒绝一个超过32个字符的字符串,并且我正在查看的字符串是兆字节,那么计算strlen(str)是愚蠢的,需要查看字符串中的每个字符。strnlen(str, 33)只会查看前33个字符,如果结果是33,我知道字符串太长。)

如果我理解您正在尝试正确检查的内容,则可以使用以下稍微简单的正则表达式:

[_[:alnum:]]([-+.]?[_[:alnum:]])*@[_[:alnum:]]([-+.]?[_[:alnum:]])*

坚持认为-+.必须在字母字符之前和之后(因此它们不能位于开头或结尾,而您不能连续两个。)

答案 1 :(得分:0)

这是你的正则表达式:

^(?=.{1,32}$)\w+([-+.]\w+)*@\w+([-+.]\w+)*.\w+([-+.]\w+)*$

你正在逃避它:

^(\?=.{1,32}$)\w+([-+.]\w+)*@\w+([-+.]\w+)*.\w+([-+.]\w+)*$

但是,你[可能]将它放入一个字符串中:

"^(\?=.{1,32}$)\w+([-+.]\w+)*@\w+([-+.]\w+)*.\w+([-+.]\w+)*$"

所以,你必须双击反斜杠:

"^(\\?=.{1,32}$)\w+([-+.]\w+)*@\w+([-+.]\w+)*.\w+([-+.]\w+)*$"

同样,使用所有反斜杠:

"^(\\?=.{1,32}$)\\w+([-+.]\\w+)*@\\w+([-+.]\\w+)*.\\w+([-+.]\\w+)*$"

但是,你可能不想逃避?,所以我们有:

"^(?=.{1,32}$)\\w+([-+.]\\w+)*@\\w+([-+.]\\w+)*.\\w+([-+.]\\w+)*$"

这是必要的,因为在字符串中,C字符串解析器可能会使用它们。剥离后,您希望regcomp [或等效]获得\w而不只是w

并非所有正则表达式包/库都支持(?=,因此如果您需要,请确保您的。 IIRC,pcre确实。