【问题标题】:Regex with attributes带有属性的正则表达式
【发布时间】:2012-12-08 04:05:34
【问题描述】:

我想解析这种代码:

{articles mode="extrait" nb="3"}

我正在使用这个正则表达式:

@\{(articles)(?:(?:\s|\ )*(?:(\w+)="(\w+)"))*\}@

但它不起作用,当我做一个 preg_match_all 时,这是一个带有 $matches 参数的 print_r 的结果:

Array (
    [0] => {articles mode="extraits" nb="3"}
    [1] => articles
    [2] => nb
    [3] => 3
)

我认为最后一个 * 应该可以获取所有属性,而不仅仅是最后一个。

您是否看到缺少或不正确的内容?

提前谢谢你

【问题讨论】:

  • 您正在重复一个捕获组,这会导致捕获组捕获最后一个匹配项。
  • 我可以补充一点,在 PHP 中无法获得任意数量的捕获。正则表达式所能做的就是首先匹配整个块,然后在块上运行第二个正则表达式以提取所有属性(在单独的匹配中)
  • 请查看类似问题的答案:stackoverflow.com/a/574968/1447613

标签: php regex parsing attributes preg-match-all


【解决方案1】:

感谢您的回答,即使我几乎不明白一些事情。

我找到了另一种更简单但仅限于 2 个参数的方法(我暂时不需要更多参数):

@\{(articles)((\s)(\w+)="(\w+)")?((\s)(\w+)="(\w+)")?\}@

Array 
( 
[0] => {articles nb="2" mode="extrait"} 
[1] => articles 
[2] => nb="2" 
[3] => 
[4] => nb 
[5] => 2 
[6] => mode="extrait" 
[7] => 
[8] => mode 
[9] => extrait 
)

然后我会做类似的事情:

if($key = array_search('mode', $option)) $mode = $option[$key + 1];

if($mode == 'extrait')
{
    // my stuff here
}

再次感谢您的所有回答!

【讨论】:

    【解决方案2】:

    正如@nickb 已经评论的那样,重复捕获组仅保留其最后一次匹配。 AFAIK,只有 .NET 提供了保留所有匹配项的实现。因此,我同意@m.buettner 的观点,即您必须至少使用两个匹配项。而@IngmardeLange 的解决方案似乎是一种替代实现,虽然我没有检查过,但仍然使用至少两个匹配项。

    为了好玩,我设计了一种使用单个匹配项来完成此操作的方法。最初的想法是对@{article 部分使用lookbehinds,但不支持可变长度lookbehinds。然后,(不幸的是,正如您将要见证的那样)我记得@TimPietzcker 曾经提到过实现可变长度后向查找的技巧:在反向字符串上进行可变长度查找aheads。 (请不要真的使用这种方法。)

    <?php
    
        function get_attr_val_matches($tag, $subject)
        {
            $regex = '/"(\w+)"=(\w+)\s+(?=(?:"\w+"=\w+\s+)*' . strrev($tag) . '\{@)/';
            preg_match_all($regex, strrev($subject), $matches, PREG_SET_ORDER);
    
            foreach ($matches as &$match)
            {
                $match = array_map(strrev, $match);
                $match = array($match[0], array_reverse(array_slice($match, 1)));
            }
    
            return array_reverse($matches);
        }
    
        $tag = 'articles';
        $subject = '@{articles mode="extrait" nb="3"}';
    
        print_r(get_attr_val_matches($tag, $subject));
    
    ?>
    

    输出:

    Array
    (
        [0] => Array
            (
                [0] =>  mode="extrait"
                [1] => Array
                    (
                        [0] => mode
                        [1] => extrait
                    )
            )
    
        [1] => Array
            (
                [0] =>  nb="3"
                [1] => Array
                    (
                        [0] => nb
                        [1] => 3
                    )
            )
    )
    

    Here's a running example.

    很明显,如果我还没有充分否认这一点,那么所有的逆转成本都不仅仅是做两场比赛。但也许有一个应用程序可以将具有可变长度后视的表达式一般转换为如上所述的反向前瞻,然后返回。虽然可能不是。

    【讨论】:

    • 标记@m.buettner,因为他会从中获得乐趣。或者是胃溃疡。
    【解决方案3】:
    $instances = array();
    
    @ preg_match_all( '/\{articles([^\}]+)\}/', $string, $articles );
    
    if ( false === empty( $articles[1][0] ))
    {
       foreach ( $articles[1] as $article )
       {
          @ preg_match_all( '/\b(\w+)="([^"]+)"/', $article, $arguments );
    
          if ( false === empty( $arguments[0][0] ))
          {
             $settings = array();
    
             foreach ( $arguments[0] as $index => $argument )
             {
                $settings[$arguments[1][$index]] = $arguments[2][$index];
             }
    
             $instances[] = $settings;
          }
    
          unset( $arguments );
       }
    }
    
    print_r( $instances );
    

    【讨论】:

      猜你喜欢
      • 2012-04-21
      • 1970-01-01
      • 1970-01-01
      • 2010-09-08
      • 1970-01-01
      • 2011-07-27
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      相关资源
      最近更新 更多