【问题标题】:Dynamic capture group name in preg_match()preg_match() 中的动态捕获组名称
【发布时间】:2015-05-18 17:23:08
【问题描述】:

在 PHP 中,是否可以创建动态命名的捕获组?

例如说我想将一个 dsn 解析成它的组件。考虑以下几点:

<?php

$dsn = 'mysql:host=localhost;dbname=mydatabase';

preg_match_all('/host=(?P<host>[^;]+);dbname=(?P<dbname>[^;]+)/', $dsn, $matches);

是否可以在不明确定义每个捕获组的名称的情况下获得相同的结果?

换句话说,匹配模式/;|:([^=]+)=([^;]+)/ 并使用等号左侧的任何内容作为组的名称,使用右侧的任何内容作为值。

我知道我可以通过以下方式模拟所需的行为:

<?php

$dsn = 'mysql:host=localhost;dbname=mydatabase';

list($engine, $dsn) = explode(':', $dsn);
$result = [];

 while(preg_match('/;?(?P<key>[^=]+)=(?P<val>[^;]+)/', $dsn, $matches)) {
    $result[$matches['key']] = $matches['val'];
    $dsn = str_replace($matches[0], '', $dsn);
}

我也知道还有其他几种方法可以实现这一目标。我不是在寻找解决方法,我想知道动态命名的捕获组是否可行,如果可行,如何实现?

【问题讨论】:

    标签: php regex


    【解决方案1】:

    不,命名的捕获组不能是动态的。您所展示的几乎是实现预期结果的唯一方法。

    【讨论】:

    • 不是我所希望的答案,而是我害怕我无论如何都会得到的答案。为你投票,但我必须接受 Casimir 的回答,因为他提供了下一个最好的东西。谢谢!
    • @Schlaus:我也想到了使用 array_combine 的解决方案,但没有发布它,因为您在问题中声明您不是在寻找另一种解决方法。大智若愚,哈哈!不过,很高兴您找到了解决方案。干杯!
    【解决方案2】:

    不,这是不可能的。

    解决方法的想法:

    $dsn = 'mysql:host=localhost;dbname=mydatabase';
    
    if (preg_match_all('~([^;:=]+)=([^;]*)~', $dsn, $matches))
        $result = array_combine($matches[1], $matches[2]);
    

    【讨论】:

    • 现在这很漂亮!我没想过使用array_combine(),但它是完成这项工作的完美工具。只是一个更正:在开始分隔符之后应该有;?,以从键中消除它。否则这是完美的,谢谢!
    • @Schlaus:我确实忘记了;,已更正。
    猜你喜欢
    • 2016-06-20
    • 1970-01-01
    • 2011-12-31
    • 1970-01-01
    • 1970-01-01
    • 2021-02-14
    • 2019-06-05
    • 1970-01-01
    • 2020-01-22
    相关资源
    最近更新 更多