【问题标题】:How many captured groups are supported by pcre2_substitute() function?pcre2_substitute() 函数支持多少捕获组?
【发布时间】:2022-12-14 23:43:29
【问题描述】:

我在我的 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】:

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

然而,一般来说,一场比赛可能会达到另一个限制,然后才能允许大量的团体:例如主题字符串的最大长度,或内部调用match()的次数(总计或递归),但可以增加匹配限制。有关匹配限制的详细信息,请参阅“The match contextpcre2api.


来自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 的值)。

  • 的最大长度名字命名子模式是 32 个代码单元。
    char 由 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 好点。第一次提到时添加了一个简短的示例和参考。
【解决方案2】:

PCRE2包

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

所以,似乎反向引用的数量

  • 未硬编码到 PCRE2
  • 很可能取决于尺寸,如果匹配限制或者匹配极限递归参数。

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

PCRE 在线参考

来自regular-expressions.info

大多数正则表达式支持最多99捕获组和两位数的反向引用。所以如果你的正则表达式有 99 个捕获组,99 是一个有效的反向引用。

还有Regular Expression Reference: Capturing Groups and Backreferences page

反向引用 9
反向引用 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 库。我建议完全删除它并将它们发布在单独的问答中。
猜你喜欢
  • 2016-02-28
  • 2020-08-25
  • 2016-09-23
  • 1970-01-01
  • 2011-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多