【发布时间】:2011-09-16 07:21:00
【问题描述】:
更新/注意:
我想我可能正在寻找的是在 PHP 中获取 captures of a group。
参考:PCRE regular expressions using named pattern subroutines.
(仔细阅读:)
我有一个包含可变数量段的字符串(简化):
$subject = 'AA BB DD '; // could be 'AA BB DD CC EE ' as well
我现在想匹配段并通过匹配数组返回它们:
$pattern = '/^(([a-z]+) )+$/i';
$result = preg_match_all($pattern, $subject, $matches);
这将只返回捕获组 2 的 last 匹配项:DD。
有没有一种方法可以通过一次正则表达式执行检索所有子模式捕获(AA、BB、DD)? preg_match_all不适合这个吗?
这个问题是一个概括性的问题。
$subject 和 $pattern 均已简化。自然,有了AA、BB、.. 这样的一般列表,使用其他函数(例如explode)或$pattern 的变体更容易提取。
但我特意询问如何使用preg_...-family 函数返回所有子组匹配项。
对于现实生活中的案例,假设您有多个(嵌套)级别的不同数量的子模式匹配。
示例
这是一个伪代码示例,用于描述一些背景。 想象一下:
令牌的常规定义:
CHARS := [a-z]+
PUNCT := [.,!?]
WS := [ ]
$subject 得到基于这些的标记。标记化存储在标记数组中(类型、偏移量、...)。
然后将该数组转换为一个字符串,每个标记包含一个字符:
CHARS -> "c"
PUNCT -> "p"
WS -> "s"
现在可以在令牌流字符串索引上运行基于令牌(而不是字符类等)的正则表达式。例如
regex: (cs)?cp
表示一组或多组字符,后跟标点符号。
因为我现在可以将自定义标记表示为正则表达式,所以下一步是构建语法。这只是一个例子,这是一种 ABNF 风格:
words = word | (word space)+ word
word = CHARS+
space = WS
punctuation = PUNCT
如果我现在将 words 的语法编译成(令牌)正则表达式,我自然希望每个 word 的所有子组匹配。
words = (CHARS+) | ( (CHARS+) WS )+ (CHARS+) # words resolved to tokens
words = (c+)|((c+)s)+c+ # words resolved to regex
到目前为止,我可以编写代码。然后我遇到了子组比赛只包含他们最后一场比赛的问题。
所以我可以选择自己为语法创建一个自动机(我想阻止它以保持语法表达式的通用性),或者在某种程度上让 preg_match 以某种方式为我工作,这样我就可以省去它了。
基本上就是这样。或许现在可以理解我为什么简化问题了。
相关:
【问题讨论】:
-
如果您将问题概括得如此之多,以至于可以给出正确答案的替代方案,那么您的问题就没有那么有价值了。如果您不想要简化的答案,请不要简化。 -1.
-
我正在寻找有关特定主题的答案。我不明白为什么简化对于使其可见是不好的,尽管我看到一定程度的抽象可能是一种负担。
-
嗯,很明显,因为您想要一个子组的答案,而您的示例不包括对子组的需求。这个例子有缺陷。
-
@Berry Langerak:简化总是有一些损失。您会发现现在添加了一个更详细的示例。
-
刚刚偶然发现:
J (PCRE_INFO_JCHANGED)-(?J)内部选项设置更改了本地PCRE_DUPNAMES选项。允许子模式的重复名称在这里可能无法解决此问题,但通常很有趣:php.net/manual/en/reference.pcre.pattern.modifiers.php
标签: php regex grammar preg-match-all