使用正则表达式替换" function"在字符串和使用选项="值"对内

时间:2012-12-03 16:19:11

标签: php regex

我要做的是用某些html块替换用户插入的文本(例如;博客文章)中的“函数”,但在“函数”中使用选项/值对。明确?没有?!这么想:)这是一个例子:

Some text, can be long, may be short, a nice story, or just a comment.
{{function option1="value1" option2="value2"}}
And some more text!
{{function2 option1="value1" option2="value2"}}

在文中,我想替换并解析{{function ...}}部分。一个更具体的例子可能是:

{{youtube videokey="_VIDEOKEY_"}}

应该由youtube嵌入代码替换:

<iframe width="420" height="315" src="http://www.youtube.com/embed/_VIDEOKEY_" frameborder="0" allowfullscreen></iframe>

为此,我想使用preg_replace_callback()函数,因此我可以有一些空间对传递的数据/选项进行一些计算。


问题:我可以获取并替换格式为这样的子串({{ ... }}),甚至匹配选项/值对,问题是我无法获得每个单个o匹配数组中的/ v对,只有 last

我尝试了很多表达式,其中一个我认为最接近的是:

\{\{\w+([[:space:]]+(([0-9a-zA-Z]+)=\"([0-9a-zA-Z]+)\"))+\}\}

如您所见,我尝试匹配:

  1. {{}}
  2. 中的字符串
  3. 其中第一部分是单词
  4. 后跟一个或多个选项/值对:
    • 一个或多个空格
    • 一个或多个字母或数字(选项名称)
    • =标志
    • "(选项值)
    • 括起来的一个或多个字母或数字
  5. 在示例中,上面的文本将匹配(使用preg_match_all):

    array(5) (
        0 => array(2) (
            0 => string(46) "{{function option1="value1" option2="value2"}}"
            1 => string(47) "{{function2 option1="value1" option2="value2"}}"
        )
        1 => array(2) (
            0 => string(17) " option2="value2""
            1 => string(17) " option2="value2""
        )
        2 => array(2) (
            0 => string(16) "option2="value2""
            1 => string(16) "option2="value2""
        )
        3 => array(2) (
            0 => string(7) "option2"
            1 => string(7) "option2"
        )
        4 => array(2) (
            0 => string(6) "value2"
            1 => string(6) "value2"
        )
    )
    

    当使用带有这个正则表达式的preg_replace_callback时,我会收到相同的匹配集(在一维数组中)。


    我有这个解决方案,但不喜欢它(因为它涉及正则表达式匹配的正则表达式,而我认为它应该可以在一个表达式中执行):

    $input = ... // see text above
    $output = preg_replace_callback('@\{\{\w+([[:space:]]+(([0-9a-zA-Z]+)=\"([0-9a-zA-Z]+)\"))+\}\}@', 'my_replace_function', $input);
    
    function my_replace_function($match) {
        preg_match_all('@([0-9a-zA-Z]+)=\"([0-9a-zA-Z]+)\"@', $match[0], $matches);
        // do something with the $matches
    }
    

    甚至可以向我的回调函数传递一个包含所有选项/值对的数组,而不仅仅是最后一个匹配,并使用该数据来解析字符串?如果是这样,你能指出我正确的方向吗?

    基本上问题是:我可以在匹配中分隔出有效的子模式吗?


    --- ---编辑 上面提出的解决方案(捕获整个'function'-block,然后匹配匹配字符串中的选项 - 值对)实际上是这个难题的解决方案。有关详细信息,请参阅下面@ m.buettner的答案(已接受的答案)。

1 个答案:

答案 0 :(得分:2)

你做不到。对不起,但就这么简单。大多数正则表达式引擎不支持使用单个捕获组捕获多个值。相当于说,大多数正则表达式引擎只支持有限和固定数量的捕获。 .NET是一个很大的例外。但是你正在使用PCRE - 并且PCRE将始终返回每个组的最后一次捕获(see here,官方引用待定;但google为“PCRE重复捕获组”,所有来源都同意)。如果组的数量由模式中括号的数量确定。有时会有可能的解决方法,您可以将重复的捕获转换为重复的匹配,但我认为这在您的情况下也不适用。

所以你的解决方案真的是正确的方法。您匹配整个{{...}}块,然后分别解析回调中的键值对。