我想要做的是用某些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()
函数,因此我可以有一些空间对传递的数据/选项进行一些计算。
{{ ... }}
问题:我可以获取和替换像这样(
我尝试了很多表达方式,我认为最接近的一种是:
\{\{\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
}
甚至可以向我的回调函数传递一个包含所有选项/值对的数组,而不仅仅是最后一个匹配项,并使用该数据来解析字符串?如果是这样,你能指出我正确的方向吗?
基本上问题是:我可以在比赛中分离重复的子模式吗?
---Edit--- The solution proposed above (capturing the whole 'function'-block, then match the option-value pairs within the matched string) is in fact the solution to this puzzle. For more detail please see the answer of @m.buettner below (the accepted one).