在 php 中用正则表达式替换简码
Replace shortcodes with regex in php
我有一个自定义 PHP 脚本,其模板文本如下所示
Color: [option]color[/option]<br />
[if option="manufacturer"]<br />
Manufacturer: [option]manufacturer[/option]<br />
[/if]<br />
Price: [option]price[/option]
我已经使用 preg_replace_callback 成功地将 [option]color[/option] 和 [option]price[/option] 替换为实际值,例如 White 和 $10.00。
我将此代码用于简单的 [option] 简码:
$template = preg_replace_callback('!\[option](\w+)\[\/option\]!',
function ($matches)
{
//Here I get a value of color, price, etc
...
return $some_value;
},
$template);
但我就是想不通如何处理IF语句...应该检查是否设置了制造商,然后替换[option]manufacturer[/option],当然还要去掉打开和关闭如果行。
结果输出应该是
Color: White<br />
Manufacturer: Apple<br />
Price: .00
或者如果没有制造商定义它应该是
Color: White<br />
Price: .00
class test {
protected $color = 'White';
protected $manufacturer = 'Apple';
protected $price = '.00';
public function __construct() {
$template = '[option]color[/option]
[option]manufacturer[/option]
[option]price[/option]';
$temp = preg_replace_callback('!\[option](\w+)\[\/option\]!',
function ($matches)
{
$value = !empty($this->$matches[1]) ? ucfirst($matches[1]) . ': ' . $this->$matches[1] . '<br />' : '';
return $value;
},
$template);
echo $temp;
}
}
new test; // call the constructor function
它产生以下输出:
Color: White <br />
Manufacturer: Apple <br />
Price: .00
如果值 'Manufacturer' 为空意味着输出变为:
Color: White <br />
Price: .00
对于 if
,您应该添加第二个 preg_replace_callback`,并按如下方式使用它:
$options['color'] = 'white';
$options['price'] = '10.00';
$template = preg_replace_callback(
'!\[if option=\"(.*)\"\](.+)\[\/if\]!sU',
function ($matches) use ($options)
{
if (isset($options[$matches[1]]))
return $matches[2];
else
return '';
},
$template
);
这里您应该注意的是正则表达式末尾的修饰符 sU
。
s
使正则表达式中的点 .
也包含换行符,因此正则表达式可以超越同一行。
U
使正则表达式变得不贪婪。你将需要这个,否则你的正则表达式可能从第一个短标签的开头开始,一直持续到最后一个短标签的结尾,只出现一次。你还没有遇到这个问题,因为你没有在任何地方的同一行上有两个短标签。但是 s
修饰符现在会引入该问题。
当然也注意到现在有两个匹配的组。第一个是if
中的选项,第二个是if
.
中的内容
最后我建议你不要在你的匿名函数中获取值,因为匿名函数会为每个 shorttag 一遍又一遍地调用。这会给你带来开销。而是使用 use
关键字获取匿名函数之外的值并传递这些值。
我有一个自定义 PHP 脚本,其模板文本如下所示
Color: [option]color[/option]<br />
[if option="manufacturer"]<br />
Manufacturer: [option]manufacturer[/option]<br />
[/if]<br />
Price: [option]price[/option]
我已经使用 preg_replace_callback 成功地将 [option]color[/option] 和 [option]price[/option] 替换为实际值,例如 White 和 $10.00。
我将此代码用于简单的 [option] 简码:
$template = preg_replace_callback('!\[option](\w+)\[\/option\]!',
function ($matches)
{
//Here I get a value of color, price, etc
...
return $some_value;
},
$template);
但我就是想不通如何处理IF语句...应该检查是否设置了制造商,然后替换[option]manufacturer[/option],当然还要去掉打开和关闭如果行。
结果输出应该是
Color: White<br />
Manufacturer: Apple<br />
Price: .00
或者如果没有制造商定义它应该是
Color: White<br />
Price: .00
class test {
protected $color = 'White';
protected $manufacturer = 'Apple';
protected $price = '.00';
public function __construct() {
$template = '[option]color[/option]
[option]manufacturer[/option]
[option]price[/option]';
$temp = preg_replace_callback('!\[option](\w+)\[\/option\]!',
function ($matches)
{
$value = !empty($this->$matches[1]) ? ucfirst($matches[1]) . ': ' . $this->$matches[1] . '<br />' : '';
return $value;
},
$template);
echo $temp;
}
}
new test; // call the constructor function
它产生以下输出:
Color: White <br />
Manufacturer: Apple <br />
Price: .00
如果值 'Manufacturer' 为空意味着输出变为:
Color: White <br />
Price: .00
对于 if
,您应该添加第二个 preg_replace_callback`,并按如下方式使用它:
$options['color'] = 'white';
$options['price'] = '10.00';
$template = preg_replace_callback(
'!\[if option=\"(.*)\"\](.+)\[\/if\]!sU',
function ($matches) use ($options)
{
if (isset($options[$matches[1]]))
return $matches[2];
else
return '';
},
$template
);
这里您应该注意的是正则表达式末尾的修饰符 sU
。
s
使正则表达式中的点 .
也包含换行符,因此正则表达式可以超越同一行。
U
使正则表达式变得不贪婪。你将需要这个,否则你的正则表达式可能从第一个短标签的开头开始,一直持续到最后一个短标签的结尾,只出现一次。你还没有遇到这个问题,因为你没有在任何地方的同一行上有两个短标签。但是 s
修饰符现在会引入该问题。
当然也注意到现在有两个匹配的组。第一个是if
中的选项,第二个是if
.
最后我建议你不要在你的匿名函数中获取值,因为匿名函数会为每个 shorttag 一遍又一遍地调用。这会给你带来开销。而是使用 use
关键字获取匿名函数之外的值并传递这些值。