首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使用preg_match_all()获取子组匹配的所有捕获?

如何使用preg_match_all()获取子组匹配的所有捕获?
EN

Stack Overflow用户
提问于 2011-06-16 19:41:34
回答 8查看 12.6K关注 0票数 19

更新/注意:

我想我可能要找的是用

写的captures of a group

参考:PCRE regular expressions using named pattern subroutines.

(请仔细阅读:)

我有一个字符串,它包含可变数量的段(简化):

$subject = 'AA BB DD '; // could be 'AA BB DD CC EE ' as well

我现在想要匹配这些片段,并通过matches数组返回它们:

$pattern = '/^(([a-z]+) )+$/i';
$result = preg_match_all($pattern, $subject, $matches);

这将只返回捕获组2的最后一个匹配项:DD

有没有办法在一次正则表达式执行中检索所有子模式捕获(AABBDD)?难道preg_match_all不适合这个吗?

这个问题是一个泛化。

$subject$pattern都得到了简化。自然有了这样的通用列表AABB,..使用其他函数(例如explode)或$pattern的变体更容易提取。

但我特别问的是,如何使用preg_...-family of functions返回所有的子组匹配。

对于现实生活中的情况,假设您有多个(嵌套的)不同数量的子模式匹配。

示例

这是一个用伪代码描述背景的例子。想象一下:

令牌的常规定义:

   CHARS := [a-z]+
   PUNCT := [.,!?]
   WS := [ ]

基于这些对$subject get进行标记化。标记化存储在一个标记数组中(type,offset,...)。

然后将该数组转换为字符串,每个令牌包含一个字符:

   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为我工作,这样我就可以节省时间。

基本上就是这样。也许现在可以理解为什么我简化了这个问题。

相关信息:

EN

回答 8

Stack Overflow用户

发布于 2014-06-18 01:23:58

类似的主题:Get repeated matches with preg_match_all()

检查选择的答案加上我的答案可能有用,我将在这里重复一遍:

来自http://www.php.net/manual/en/regexp.reference.repetition.php

重复捕获子模式时,捕获的值是与最终迭代匹配的子字符串。

我个人放弃了,我会分两步来做。

编辑

我在另一个线程中看到了someone声称lookbehind方法能够做到这一点。

票数 4
EN

Stack Overflow用户

发布于 2011-06-16 19:51:30

试试这个:

preg_match_all("'[^ ]+'i",$text,$n);

$n[0]将包含文本中所有非空格字符组的数组。

编辑:带有子组的

preg_match_all("'([^ ]+)'i",$text,$n);

现在,$n[1]将包含与$n[0]完全相同的子组匹配。这实际上是毫无意义的。

Edit2:嵌套子组示例:

$test = "Hello I'm Joe! Hi I'm Jane!";
preg_match_all("/(H(ello|i)) I'm (.*?)!/i",$test,$n);

结果是:

Array
(
    [0] => Array
        (
            [0] => Hello I'm Joe!
            [1] => Hi I'm Jane!
        )

    [1] => Array
        (
            [0] => Hello
            [1] => Hi
        )

    [2] => Array
        (
            [0] => ello
            [1] => i
        )

    [3] => Array
        (
            [0] => Joe
            [1] => Jane
        )

)
票数 3
EN

Stack Overflow用户

发布于 2011-06-17 02:25:15

有没有一种方法可以用一次正则表达式执行来检索所有的匹配(AA,BB,DD)?preg_match_all不是不适合这样做吗?

您当前的正则表达式似乎用于preg_match()调用。试着这样做:

$pattern = '/[a-z]+/i';
$result = preg_match_all($pattern, $subject, $matches);

根据评论,我提到的ruby正则表达式:

sentence = %r{
(?<subject>   cat   | dog        ){0}
(?<verb>      eats  | drinks     ){0}
(?<object>    water | bones      ){0}
(?<adjective> big   | smelly     ){0}
(?<obj_adj>   (\g<adjective>\s)? ){0}
The\s\g<obj_adj>\g<subject>\s\g<verb>\s\g<opt_adj>\g<object>
}x

md = sentence.match("The cat drinks water");
md = sentence.match("The big dog eats smelly bones");

但是我认为你需要一个词法分析器/解析器/记号赋予器在PHP中做同样的事情。:-|

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6371226

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档