Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
&引用;“正则表达式太大”;PHP中的错误_Php_Regex - Fatal编程技术网

&引用;“正则表达式太大”;PHP中的错误

&引用;“正则表达式太大”;PHP中的错误,php,regex,Php,Regex,我正在研究一个相对复杂、非常大的正则表达式。它当前为41127个字符,并且可能会随着附加案例的增加而有所增加。我开始在PHP中遇到以下错误: preg_match_all():编译失败:正则表达式在偏移量41123处太大 有没有办法增加大小限制?其他地方建议的以下设置不起作用,因为这些设置适用于数据大小,而不是正则表达式大小: ini_set("pcre.backtrack_limit", "100000000"); ini_set("pcre.recursion_limit", "100000

我正在研究一个相对复杂、非常大的正则表达式。它当前为41127个字符,并且可能会随着附加案例的增加而有所增加。我开始在PHP中遇到以下错误:

preg_match_all():编译失败:正则表达式在偏移量41123处太大

有没有办法增加大小限制?其他地方建议的以下设置不起作用,因为这些设置适用于数据大小,而不是正则表达式大小:

ini_set("pcre.backtrack_limit", "100000000");
ini_set("pcre.recursion_limit", "100000000");
或者,是否有办法在正则表达式中定义一个“子模式变量”,该变量可以在正则表达式中的不同位置重复?(我不是说重复使用
*
+
,甚至重复匹配的“1”)?实际上,我使用的PHP变量包含在正则表达式中少数地方重复的子模式,但这会导致正则表达式在传递给PRCE函数之前进行扩展

这是一个复杂的正则表达式,不能用使用
strpos
或类似建议的更简单的关键字搜索来代替


我宁愿避免在
|
处将其拆分为子表达式,并尝试分别匹配子表达式,因为大小的减少是适度的(只有2或3个顶级
|
),这将使进一步的开发复杂化。

我不同意有更好的方法来实现这一点的评论,但我将在这里回答这个问题

您可以增加正则表达式的最大大小,但只能通过自己重新编译PHP。正因为如此,您的代码根本不可移植,如果您使用的是预编译的二进制文件,那么您就不走运了

也就是说,我建议找到一个匹配的替代方案

有关评论,请参阅

PCRE将其编译代码中的偏移量保持为2字节量 (始终以大端顺序存储)默认情况下。这些都是用来 例如,从子模式的开始链接到其备选方案 以及它的结束。每个偏移量使用2个字节会限制 将正则表达式编译为64K左右,这足以容纳几乎 每个人然而,我收到了一个更大限额的请求。 出于这个原因,并且为了使代码更易于维护 存储和加载来自字节字符串的偏移量现在可以处理了 通过此处定义的宏

宏是 由链接大小的值控制。默认情况下,该值为2 config.h文件,但可以通过在命令行上使用-D来重写。 这在Unix系统上通过“configure”命令实现自动化

因此,您可以从PHP源代码发行版编辑
ext/pcre/pcrelib/config.h
以增加大小限制,或者在编译
/configure-DLINK\u size=4


编辑:如果您试图匹配/解析HTML,我建议使用来解析HTML,然后遍历DOM树或构建XPATH来查找所需内容。

根据应用程序的不同,有效的解决方案有:

  • 使用DEFINE for any redundant sub Expression缩短正则表达式(见下文)
  • 通过重新编译PHP增加正则表达式大小的最大限制(参见drew010的精彩答案)。尽管这可能并非在所有环境中都可用,或者在更改服务器时可能会产生兼容性问题
  • |
    拆分正则表达式,并分别处理生成的子表达式。如果正则表达式本质上是由
    |
    分隔的多个关键字,那么转换为strtok或带有strpos的循环可能是更好更快的选择
  • 使用其他语言/regex引擎,例如C++/Boost,尽管我没有验证这一点
我的具体问题的解决方案:根据Mario的评论,使用
(?(DEFINE)…)
构造一些被多次重复使用的子表达式,将我的正则表达式大小从41127个字符减少到“仅”4071个,这是一个消除“正则表达式太大”错误的优雅解决方案


请参阅:

尝试使用数组块分割数组,然后在foreach()中使用preg\u match\u all。我使用的是完全相同的代码,我有一个40k+数组,所以我通过上面的解决方案,但没有解决我的“编译失败:正则表达式在偏移量处太大”问题,然后我将我的40k+数组拆分为4个1k元素数组,并在preg_match_all条件上使用foreach(),瞧!成功了

你能把绳子切成碎片吗?当事情变得太大时,这是一个信号,表明事情不对劲。这个怪物是做什么的?它可能会从均衡饮食和定期梳洗中受益。打赌一百万美元是更好的方法您可以使用
\N
模式匹配先前匹配的组,其中
N
是组数。这通常是在匹配引号时完成的,如
\w+=(['“]).\1
()。但实际上,这可能会被分割成许多较小的模式,每个模式单独处理。当您有一个41k正则表达式时,您显然需要不同的方法…您提出了错误的问题。好的有用答案可能“修复了问题”“。但是,我宁愿远离重新编译PHP&相关的兼容性问题,除非我必须这样做。谢谢。因此要澄清:如果您想增加最大正则表达式大小,那么必须重新编译PHP。此命令行没有运行时选项。命令行<代码>-D不存在。使用
php-d DLINK\u SIZE=4 myScript.php(或6或10),没有效果。@PeterKrauss
-DLINK\u SIZE=4
不是php选项,而是编译php时使用的选项。您不能在运行时更改正则表达式的大小,这是编译时的一个构建选项。