我想使用正则表达式来验证用户输入.我想允许字母,数字,空格,逗号,撇号,句号,感叹号和问号的任意组合,但我还想将输入限制为4000个字符.我想出了以下正则表达式来实现这一点:/^([a-z]|[0-9]| |,|'|\.|!|\?){1,4000}$/i
.
但是,当我尝试使用这个正则表达式在PHP中使用preg_match()测试一个主题时,我会收到一个警告:PHP Warning: preg_match(): Compilation failed: regular expression is too large at offset 37
并且主题无法测试.
我发现这很奇怪,因为如果我使用无限量词,测试通过就好了(我在下面演示了这种情况).
为什么将重复限制在4000个问题,但无限重复?
正则表达式-test.php的:
<?php
$infinite = "/^([a-z]|[0-9]| |,|'|\.|!|\?)*$/i"; // Allows infinite repetition
$fourk = "/^([a-z]|[0-9]| |,|'|\.|!|\?){1,4000}$/i"; // Limits repetition to 4000
$string = "I like apples.";
if ( preg_match($infinite, $string) ){
echo "Passed infinite repetition. \n";
}
if ( preg_match($fourk, $string) ){
echo "Passed maximum repetition of 4000. \n";
}
?>
Run Code Online (Sandbox Code Playgroud)
回声:
Passed infinite repetition
PHP Warning: preg_match(): Compilation failed: regular expression is too large at offset 37 in regex-test.php on line 16
Run Code Online (Sandbox Code Playgroud)
该错误是由于它的LINK_SIZE
偏移值将编译的模式大小限制为64K.这是一种预期的行为,如下所述,并不是因为重复的限制以及编译时如何解释模式.
正如Alan Moore在他的回答中指出的那样,所有角色都应该在同一个角色类中.我更激烈,所以请允许我说这种模式是这样错了,它令我生厌.
- 没有进攻,我们大多数人也曾尝试过.这只是一种强调,不应该使用这种结构的尝试.
这里有3个常见的陷阱(x|y|z){1,4000}
:
|
s)增加了回溯状态.尝试尽可能减少它们是一种很好的做法.在这种情况下,正则表达式^[ !',.0-9?A-Z]{1,4000}$/i
将完全相同,不仅可以避免错误,还可以提供更好的性能.从" 处理非常大格局 "在pcrebuild手册页:
在编译模式中,偏移值用于从一个部分指向另一个部分(例如,从左括号到交替元字符).默认情况下,在8位和16位库中,两个字节的值用于这些偏移,从而导致大约64K的编译模式的最大大小.
这意味着对于组的每次重复,编译的模式为交替中的每个子模式存储偏移值.在这种情况下,偏移量不会为已编译模式的其余部分留下任何内存.
这在PHP dist的pcre_internal.h中的注释中更清楚地表达出来:
PCRE默认将其编译代码中的偏移量保持为2字节数量(始终以big-endian顺序存储).例如,这些用于从子模式的开头到其替代项及其结尾的链接.每个偏移量使用2个字节会将编译的正则表达式的大小限制在64K左右,这对于几乎所有人来说都足够大了.
使用pcretest,我得到以下信息:
PCRE version 8.37 2015-04-28
/^([a-z]|[0-9]| |,|'|\.|!|\?){1,575}$/i
Failed: regular expression is too large at offset 36
/^([a-z]|[0-9]| |,|'|\.|!|\?){1,574}$/i
Memory allocation (code space): 65432
Run Code Online (Sandbox Code Playgroud)
关于PCRE中的其他大小限制,您可以查看我的这篇文章.
LINK_SIZE
PHP中的默认值如果我们有一个真正的理由使用一个巨大的模式,并且这种模式无法通过任何方式进一步简化,那么链接大小可能会增加.但是,您只能通过自己重新编译PHP来实现这一点(因此,从现在开始,您的代码将无法移植).它应该是最后的手段,只要别无选择.
宏由值控制
LINK_SIZE
.在config.h文件中默认为2 ,但可以通过-D
在命令行上使用来覆盖.这在Unix系统上通过"configure"命令自动完成.
PCRE链接大小可以配置为3或4:
./configure -DLINK_SIZE=4
Run Code Online (Sandbox Code Playgroud)
但请记住,较长的偏移量需要额外的数据,并且会减慢对preg_*
函数的所有调用.
如果您自己编译PHP,请参阅在Unix系统上安装或在Windows上构建您自己的PHP.
归档时间: |
|
查看次数: |
1466 次 |
最近记录: |