【发布时间】:2011-04-10 12:43:30
【问题描述】:
我一直在尽力避免来这里问这个问题,并坚持我可以自己解决。我已经这样做了,但我想我还是会来这里 1) 分享我的解决方案或 2) 获得更好的解决方案。
我知道已经有很多关于这个的 stackoverflow 问题,大多数人说使用 PEAR 库,但没有一个是关于我的具体问题。
基本上我希望能够解析 bbcode 引用标签,但是这个引用可以有可变数量的属性或根本没有属性,所以一个简单的 preg_replace 不会像下划线那样工作标记。
一个字符串中也可以有多个引号标签,这是我如何解决它的一个示例。谁能建议一种更好的方法来避免多个正则表达式和 foreach 循环?
(应该注意我正在解析示例中的强标记,但我在代码的其他地方执行此操作,这是我在此处特别苦苦挣扎并询问的引号)
$string = "[quote name='Rob' user_id='1' id='1' timestamp='1294120376']
My text here
[/quote]
[quote name='Rob' user_id='1' id='2' timestamp='1302442553']
Lorem ipsum dolor sit amet
[/quote]
Test Comment";
preg_match_all('/\[quote(.*?)](.*?)\[\/quote\]/msi', $string, $matches);
$quotes = array();
foreach($matches[1] as $id => $match)
{
preg_match_all('/(\w*?)=\'(.*?)\'/msi', $match, $attr_matches);
array_push($quotes, array(
'text' => trim($matches[2][$id]),
'attributes' => array_combine($attr_matches[1], $attr_matches[2])
));
}
echo '<pre>'.print_r($quotes,1).'</pre>';
这将输出以下内容:
Array
(
[0] => Array
(
[text] => My text here
[attributes] => Array
(
[name] => Rob
[user_id] => 1
[id] => 1
[timestamp] => 1294120376
)
)
[1] => Array
(
[text] => Lorem ipsum dolor sit amet
[attributes] => Array
(
[name] => Rob
[user_id] => 1
[id] => 2
[timestamp] => 1302442553
)
)
)
然后我简单地构建 HTML
$bbcode = '';
foreach($quotes as $quote)
{
$attributes = array();
foreach($quote['attributes'] as $key => $value)
{
switch($key)
{
case 'id':
$attributes[] = '<a href="'.site_url('forums/findpost/'.$value).'">Permalink</a>';
break;
case 'name':
if(isset($quote['attributes']['user_id']))
{
$attributes[] = 'By <a href="'.site_url('user/profile/'.$quote['attributes']['user_id'].'/'.$value).'">'.$value.'</a>';
}
else
{
$attributes[] = 'By '.$value;
}
break;
case 'timestamp':
$attributes[] = 'On '.date('d F Y - H:i A', $value);
break;
}
}
if(!empty($attributes))
{
$bbcode .= '<p class="citation">'.implode(' | ', $attributes).'</p>';
}
$bbcode .= '<blockquote>
'.$quote['text'].'
</blockquote>';
}
echo $bbcode;
这将输出以下内容:
<p class="citation">By <a href="http://domain.com/user/profile/1/Rob.html">Rob</a> | <a href="http://domain.com/forums/findpost/1.html">Permalink</a> | On 04 January 2011 - 05:52 AM</p>
<blockquote>
My text here
</blockquote>
<p class="citation">By <a href="http://domain.com/user/profile/1/Rob.html">Rob</a> | <a href="http://domain.com/forums/findpost/2.html">Permalink</a> | On 10 April 2011 - 14:35 PM</p>
<blockquote>
Lorem ipsum dolor sit amet
</blockquote>
所以这似乎是一个非常漫长而迂回的方法,但我无法理解另一种方法。有人...?
【问题讨论】:
-
当你得到这样的输入时它会失败:
[quote ...] foo [quote ...] bar [/quote] foo [/quote] -
为了我的目的,引号内的引号永远不会发生,但一个简单的解决方案是将它放在一个函数中并递归调用它。
-
好的。但是你不能简单地递归调用它(至少,不能不改变你的正则表达式)。您将替换
[quote ...] foo [quote ...] bar [/quote]并留下[/quote]悬空。