更新/注释:
我想我可能正在寻找在PHP中获取组的捕获。
(仔细阅读:)
我有一个包含可变数量段落的字符串(简化版):
$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的最后一个匹配项:
DD
。有没有办法使用一次正则表达式执行检索所有子模式捕获(
AA
、BB
、DD
)?preg_match_all
不适用吗?这个问题是一个概括。
$subject
和$pattern
都被简化了。自然地,使用其他函数(例如explode
)或$pattern
的变体从这样的AA
、BB
等的一般列表中提取更容易。但是我特别询问如何使用
preg_...
系列函数返回所有子组匹配项。对于现实情况,请想象您有多个(嵌套的)级别的变量数量的子模式匹配项。
示例
这是一个伪代码示例,用于描述背景。 想象一下以下内容:
标记的常规定义:
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 = (CHARS+) | ( (CHARS+) WS )+ (CHARS+) # words resolved to tokens
words = (c+)|((c+)s)+c+ # words resolved to regex
我能编写代码到这个程度。然后我遇到了一个问题,子组匹配只包含它们的最后一个匹配。
所以我有两个选择:要么自己为语法创建一个自动机(但我希望保持语法表达式的通用性),要么以某种方式让 preg_match 对我起作用,这样我就可以节省时间。
基本上就是这样。现在可能明白我为什么简化了问题。
相关:
preg_split
能被外推吗?[按分隔符拆分字符串,但如果转义则不拆分] (https://dev59.com/nG025IYBdhLWcg3wEhZb)。 - hakre