使用正则表达式发送电子邮件的最小和最大长度有限但错误
limited minimum and maximum length to email with regex but error
下面的正则表达式有没有错误:
^(?=.{1,32}$)\w+([-+.]\w+)*@\w+([-+.]\w+)*.\w+([-+.]\w+)*$
我使用此正则表达式模式检查电子邮件格式和长度,但执行时出现以下错误消息:
Invalid use of repetition operators such as using '*' as the first character.
我尝试在我的正则表达式前面使用\
来转义?
,regcomp()
可以编译成功但结果是错误的。
这是我的检查字符串:
test.test@test.com --> failed, wrong result
test:test@test.com --> failed, right result
环境
Operating System :
Linux debian8 3.16.0-4-686-pae #1 SMP Debian
3.16.7-ckt11-1+deb8u5 (2015-10-09) i686 GNU/Linux
GCC
Using built-in specs. COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i586-linux-gnu/4.9/lto-wrapper
Target: i586-linux-gnu Configured with: ../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 Thread model: posix gcc version 4.9.2 (Debian 4.9.2-10)
根据您的标签和您正在使用 regcomp
的提示,我假设您正在使用标准 Posix 库 regcomp
和 regexec
函数进行正则表达式匹配。
regcomp
使用的正则表达式语法在 man 7 regex
(or in Posix itself 中有完整的记录,我觉得它更易读)。有许多其他语言的正则表达式库实现了更多种类的正则表达式语法,但您没有使用那些其他语言。因此,如果您使用的语法不在那些文档中,它就不会起作用。其中包括:
- 前瞻断言,如
(?=.{1,32}$)
。事实上,没有环视断言,也没有任何其他以 (?
. 开头的语法
- 使用
\w
表示字母数字字符。如果您使用扩展正则表达式(通过提供 REG_EXTENDED
作为 regcomp
的第三个参数——您应该 总是 这样做),那么 \
的作用是防止后面的正则表达式运算符具有特殊含义。然而,Gnu 实现确实提供了一些扩展。它处理反向引用,即使 Posix 只在基本正则表达式中定义它们。有些版本确实处理 \w
和朋友,但这可能不适用于其他 Posix 正则表达式实现,例如 Mac OS X.
可以用Posix字符classes来得到\w
、\W
、\s
等的效果,例如word字符(\w
)可以写成字符class[_[:alnum:]]
,非space字符(\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
,是Posix2008年的;用glibc实现的,好处是如果只需要知道字符串不太长,strnlen
避免查看太多字符。也就是说,如果我要拒绝超过 32 个字符的字符串,而我正在查看的字符串是兆字节,那么计算 strlen(str)
会很愚蠢,这需要查看字符串中的每个字符。strnlen(str, 33)
只会查看前 33 个字符,如果结果是 33,我就知道字符串太长了。)
如果我能正确理解您要检查的内容,您可以使用以下稍微简单一些的正则表达式:
[_[:alnum:]]([-+.]?[_[:alnum:]])*@[_[:alnum:]]([-+.]?[_[:alnum:]])*
坚持认为 -
、+
和 .
如果存在,则必须在单词字符之前和之后(因此它们不能位于开头或结尾,而且你不能连续有两个。)
这是你的正则表达式:
^(?=.{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
.
并非所有正则表达式 packages/libraries 都支持 (?=
,因此如果您需要,请确保您的正则表达式支持。 IIRC,pcre
确实如此。
下面的正则表达式有没有错误:
^(?=.{1,32}$)\w+([-+.]\w+)*@\w+([-+.]\w+)*.\w+([-+.]\w+)*$
我使用此正则表达式模式检查电子邮件格式和长度,但执行时出现以下错误消息:
Invalid use of repetition operators such as using '*' as the first character.
我尝试在我的正则表达式前面使用\
来转义?
,regcomp()
可以编译成功但结果是错误的。
这是我的检查字符串:
test.test@test.com --> failed, wrong result
test:test@test.com --> failed, right result
环境
Operating System :
Linux debian8 3.16.0-4-686-pae #1 SMP Debian 3.16.7-ckt11-1+deb8u5 (2015-10-09) i686 GNU/Linux
GCC
Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/i586-linux-gnu/4.9/lto-wrapper Target: i586-linux-gnu Configured with: ../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 Thread model: posix gcc version 4.9.2 (Debian 4.9.2-10)
根据您的标签和您正在使用 regcomp
的提示,我假设您正在使用标准 Posix 库 regcomp
和 regexec
函数进行正则表达式匹配。
regcomp
使用的正则表达式语法在 man 7 regex
(or in Posix itself 中有完整的记录,我觉得它更易读)。有许多其他语言的正则表达式库实现了更多种类的正则表达式语法,但您没有使用那些其他语言。因此,如果您使用的语法不在那些文档中,它就不会起作用。其中包括:
- 前瞻断言,如
(?=.{1,32}$)
。事实上,没有环视断言,也没有任何其他以(?
. 开头的语法
- 使用
\w
表示字母数字字符。如果您使用扩展正则表达式(通过提供REG_EXTENDED
作为regcomp
的第三个参数——您应该 总是 这样做),那么\
的作用是防止后面的正则表达式运算符具有特殊含义。然而,Gnu 实现确实提供了一些扩展。它处理反向引用,即使 Posix 只在基本正则表达式中定义它们。有些版本确实处理\w
和朋友,但这可能不适用于其他 Posix 正则表达式实现,例如 Mac OS X.
可以用Posix字符classes来得到\w
、\W
、\s
等的效果,例如word字符(\w
)可以写成字符class[_[:alnum:]]
,非space字符(\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
,是Posix2008年的;用glibc实现的,好处是如果只需要知道字符串不太长,strnlen
避免查看太多字符。也就是说,如果我要拒绝超过 32 个字符的字符串,而我正在查看的字符串是兆字节,那么计算 strlen(str)
会很愚蠢,这需要查看字符串中的每个字符。strnlen(str, 33)
只会查看前 33 个字符,如果结果是 33,我就知道字符串太长了。)
如果我能正确理解您要检查的内容,您可以使用以下稍微简单一些的正则表达式:
[_[:alnum:]]([-+.]?[_[:alnum:]])*@[_[:alnum:]]([-+.]?[_[:alnum:]])*
坚持认为 -
、+
和 .
如果存在,则必须在单词字符之前和之后(因此它们不能位于开头或结尾,而且你不能连续有两个。)
这是你的正则表达式:
^(?=.{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
.
并非所有正则表达式 packages/libraries 都支持 (?=
,因此如果您需要,请确保您的正则表达式支持。 IIRC,pcre
确实如此。