【问题标题】:How many captured groups are supported by pcre2_substitute() function?pcre2_substitute() 函数支持多少个捕获的组?
【发布时间】:2016-02-28 15:18:07
【问题描述】:

我在我的 c++ 项目中使用pcre2_substitute() 函数来执行正则表达式替换:

int ret=pcre2_substitute(
  re,                    /*Points to the compiled pattern*/
  subject,               /*Points to the subject string*/
  subject_length,        /*Length of the subject string*/
  0,                     /*Offset in the subject at which to start matching*/
  rplopts,               /*Option bits*/
  0,                     /*Points to a match data block, or is NULL*/
  0,                     /*Points to a match context, or is NULL*/
  replace,               /*Points to the replacement string*/
  replace_length,        /*Length of the replacement string*/
  output,                /*Points to the output buffer*/
  &outlengthptr          /*Points to the length of the output buffer*/
);

This is the man page of the function。它没有说有多少捕获的组是可能的。我已经测试过$01${6}$12 可以工作,但限制是多少?

我检查了是否有像 C++ std::regex 这样的数字限制,但没有。 $000000000000001$1 一样工作,而在 std::regex 中则意味着 $00,其余的将被视为字符串。

我用于测试的代码是this one。 您将需要 pcre2 库来运行此代码。

【问题讨论】:

  • 仅供参考。标题声明backreferences,但反向引用是正则表达式中引用捕获数据的结构。在替换方面,捕获缓冲区只是变量。
  • 另外,我在您的代码 (this one) 中注意到您的正则表达式包含 4 个捕获组。但是,您正在尝试替换 $1234。那是捕获组号1,234 不是捕获组1、2、3、4。对于真正的测试,以编程方式创建一个包含大约 10,000 个捕获组的正则表达式。设置适当的主题字符串。然后尝试使用 $1234 进行替换。
  • @sln 我必须测试各种场景,示例代码只是其中之一。我用 1111 美元测试了超过 1111 个捕获的组,它给出了正确的结果。无论如何,问题是solved

标签: c++ regex pcre


【解决方案1】:

PCRE2 包

pcre2-10.20\README 中写到,PCRE2 有一个计数器,用于限制模式中括号的嵌套深度。这限制了模式在编译时使用的系统堆栈数量。默认值为 250,但您可以通过设置来更改它,例如,--with-parens-nest-limit=500 并且 PCRE2 有一个计数器,可以设置它来限制它在匹配模式时使用的资源量。如果在匹配期间超出限制,则匹配失败。默认值为一千万。您可以通过设置更改默认值,例如--with-match-limit=500000

看来,反向引用的数量

  • 没有硬编码到 PCRE2 中
  • 如果 match limitmatch limit recursion 参数很可能取决于大小。

由于您自己构建库,因此您可以进一步增加。

PCRE 在线参考

来自regular-expressions.info

大多数正则表达式支持多达 99 个捕获组和两位数的反向引用。因此,如果您的正则表达式有 99 个捕获组,\99 是一个有效的反向引用。

还有Regular Expression Reference: Capturing Groups and Backreferences page

反向引用 \1\9
反向引用 \10\99

请注意,“大多数”作者必须指的是主要的正则表达式引擎(PHP、JavaScript、Python、.NET),而不是仅支持的 POSIX BRE、POSIX ERE、GNU BRE、GNU ERE 正则表达式风格反向引用高达\9

但是,在pcre.txt中,有一行。

\ddd 带有八进制代码 ddd 或反向引用的字符

因此,根据本文档,可以有 999 个组。

【讨论】:

  • ${112}${1111} 工作,可能是 $9999 (4, 9s) 也存在。我开始认为没有限制....
  • 您能告诉我您是如何测试的吗?我刚刚尝试在替换模式中使用'${100}',以及it returned as a literal ${100}
  • 我想是的。PHP 使用 pcre。 pcre 中模式的最大大小取决于构建它的配置。这是 1000 万次匹配、1000 万次递归匹配和 250 个嵌套括号的默认配置......实际上是无限的......:D
  • 好吧,那就太好了。我也会尝试运行测试。
  • 请注意,PHP 中的替换限制是由于 PHP 实现了preg_replace(特别是preg_get_backref),而不是 PCRE 的限制。无论如何,关于 PHP 的部分完全偏离了这个问题,它要求 PCRE 库的限制。我建议将其完全删除,然后在单独的问答中发布。
【解决方案2】:

捕获组的最大数量为 65,535。这也是在模式或替换中可以反向引用的最大组数。

但是,一般来说,匹配可能会在允许大量组之前达到另一个限制:例如主题字符串的最大长度,或内部调用match() 的次数(总共调用或递归调用),但可以增加匹配限制。有关匹配限制的详细信息,请参阅 pcre2api 中的“The match context”。


来自pcre2limits man page

括号内的子模式的数量没有限制, 但捕获子模式不能超过 65,535 个。

然而,括号内的嵌套深度是有限制的 各种子模式。这是为了限制数量 编译时使用的系统堆栈。 PCRE2时可以指定限制 建成;默认为 250。

命名子模式的最大数量为 10,000。

菲利普·黑泽尔。最后更新时间:2014 年 11 月 25 日。 - *截至 PCRE2 版本 10.20


PCREPCRE2 的大小限制

PCRE 和 PCRE2 具有相同的限制:

  • 重复量词中的所有值都限制为 65,535。

  • 无限数量的带括号的子模式
    (尽管它仅限于各种带括号的子模式的嵌套深度)。

  • 65,535 捕获子模式

  • 10,000 个命名子模式

  • 默认的最大嵌套括号深度为 250
    PCRE2_CONFIG_PARENSLIMIT 的值)。

  • 命名子模式的 names 的最大长度为 32 个代码单元。
    一个字符由 1+ code units 表示(取决于编码)。例如。在 UTF-8 中,“Ç”有 2 个代码单元:0xC3 0x87

  • 向后引用的数量没有限制。

  • 对后续子模式的前向引用数量限制约为 200,000。

  • 控制动词中使用的名称限制为 255(8 位)和 65,535(16 或 32 位)。

  • PCRE2_CONFIG_MATCHLIMIT 的默认值为 10,000,000 (10m)。

  • PCRE2_CONFIG_RECURSIONLIMIT 的默认值为 10,000,000 (10m)。
    此限制仅适用于设置为小于 MATCH_LIMIT)。

  • 如果使用默认的内部链接大小 2 进行编译,编译模式的最大长度为 64K 代码单元(有关详细信息,请参阅pcre2build documentation)。

    李>
  • 主题字符串的最大长度是整数变量可以容纳的最大正数(可能是~1.8E+19)。但是,可用的堆栈空间可能会限制某些模式可以处理的主题字符串的大小。
    主题字符串的最大长度(以代码为单位)比PCRE2_SIZE 变量可以容纳的最大数字小一。 PCRE2_SIZE是无符号整数类型,通常定义为size_t

【讨论】:

  • @sln 好点。添加了一个简短的示例并在第一次提到时参考。
猜你喜欢
  • 2022-12-14
  • 1970-01-01
  • 2020-08-25
  • 1970-01-01
  • 2023-04-05
  • 2016-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多