我要做的是用某些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]+)\"))+\}\}
如您所见,我尝试匹配:
{{
和}}
=
标志"
(选项值)在示例中,上面的文本将匹配(使用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的答案(已接受的答案)。
答案 0 :(得分:2)
你做不到。对不起,但就这么简单。大多数正则表达式引擎不支持使用单个捕获组捕获多个值。相当于说,大多数正则表达式引擎只支持有限和固定数量的捕获。 .NET是一个很大的例外。但是你正在使用PCRE - 并且PCRE将始终返回每个组的最后一次捕获(see here,官方引用待定;但google为“PCRE重复捕获组”,所有来源都同意)。如果组的数量由模式中括号的数量确定。有时会有可能的解决方法,您可以将重复的捕获转换为重复的匹配,但我认为这在您的情况下也不适用。
所以你的解决方案真的是正确的方法。您匹配整个{{...}}
块,然后分别解析回调中的键值对。