4

所以我实际上存储了一个 html 字段,但我想添加一些伪标签以使其更易于发布。IE 我想将标题/标题包装到这个标签中: << ... >> EG << My Header >> 然后我会枚举它们,格式化并显示下面的文本。

例如:

<<News>>
Breaking news on Sunday.
Have been taking hostages.
<<General Information>>
We would want to recieve our blabla.
And you want it.
<<User Suggestions>>
Yeah we want it so much...

实际应该显示:

<H1 class="whatever" ID="Product_Header_1">News<H1>
Breaking news on Sunday.
Have been taking hostages.
<H1 class="whatever" ID="Product_Header_2">General Information</H1>
We would want to recieve our blabla.
And you want it.
<H1 class="whatever" ID="Product_Header_3">User Suggestion</H1>
Yeah we want it so much...

然后应该返回一个包含实际标题及其编号的数组,这样我就可以在页面的其他地方使用它来进行引用。

所以看起来我们可以直接替换它们,但这可能会在枚举和返回值时出现问题,并且在未关闭标签的情况下可能会失败。

或者,将它们分成一个数组,然后手动进行,这似乎是一种更好的方法。

这是我到目前为止所尝试的:

$TEXT_A=preg_split('/<<([^>]+)>>/', $TEXT);

foreach($TEXT_A as $key => $val){
    if ($key>0) echo "<br>-!-";
    echo $val;
}

其中 $TEXT 是带有伪标签的 HTML 文本。

但是问题是, split 本身并不返回正则表达式匹配,所以我对如何提取它感到困惑。也许我需要编写一些自定义函数来返回一组文本和标题,而不是常规拆分,但我不知道从哪里开始......

请帮忙。

4

5 回答 5

2

只需使用

$text_a = preg_split('/<<([^>]+)>>/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);

您会在$text_a. 假设您想忽略第一个标题之前的内容:

$n = count($text_a);
$head_a = array();
$body_a = array();
for ($i = 1; $i < $n; $i += 2) {
   $head_a[] = $text_a[$i];
   $body_a[] = $text_a[$i + 1]; // trim()?
}
于 2012-06-11T21:58:45.420 回答
1

这是一个使用preg_replace_callback. 它使用非贪婪捕获组与正向前瞻 ( (?=<<|$)) 相结合来捕获“正文”文本。积极的前瞻表示“断言存在开头分隔符<<或字符串结尾$”。

$count = 0;
$TEXT_A = preg_replace_callback( '/<<([^>]+)>>(.*?)(?=<<|$)/s', 
    function( $matches) use (&$count) {
        $count++;
        return '<H1 class="whatever" ID="Product_Header_' . $count . '">' . $matches[1] . '</H1>' . "\n" . trim( $matches[2]) . "\n\n"; 
}, $TEXT);
echo htmlentities( $TEXT_A);

我通过 htmlentities 传递它以显示生成的 HTML,但您当然可以删除该调用以查看浏览器解释的 HTML:

<H1 class="whatever" ID="Product_Header_1">News</H1>
Breaking news on Sunday.
Have been taking hostages.

<H1 class="whatever" ID="Product_Header_2">General Information</H1>
We would want to recieve our blabla.
And you want it.

<H1 class="whatever" ID="Product_Header_3">User Suggestions</H1>
Yeah we want it so much...

演示

编辑:

这是一个没有匿名函数的解决方案:

function do_replacement( $matches){
    static $count = 0;
    $count++;
    return '<H1 class="whatever" ID="Product_Header_' . $count . '">' . $matches[1] . '</H1>' . "\n" .
    trim( $matches[2]) . "\n\n";    
}

$TEXT_A = preg_replace_callback( '/<<([^>]+)>>(.*?)(?=<<|$)/s', 'do_replacement', $TEXT);
echo htmlentities( $TEXT_A);

最终编辑

此编辑包括一个全局数组来捕获替换。

$custom_array = array();
function do_replacement( $matches){
    global $custom_array;
    static $count = 0;
    $count++;
    $custom_array[$count] = $matches[1];
    return '<H1 class="whatever" ID="Product_Header_' . $count . '">' . $matches[1] . '</H1>' . "\n" .
    trim( $matches[2]) . "\n\n";    
}

$TEXT_A = preg_replace_callback( '/<<([^>]+)>>(.*?)(?=<<|$)/s', 'do_replacement', $TEXT);
echo htmlentities( $TEXT_A);

var_dump( $custom_array);
于 2012-06-11T22:05:50.730 回答
1

听起来您想使用标记格式而不是 HTML 来编写文档。

这是一个相当普遍的要求,人们已经为此提出了许多解决方案。如果您还想创建自己的标记格式,这很好,但如果您想节省一点时间,您可能需要考虑现有的一种。

在我的脑海中,我可以想到 BBCode、Markdown 和 Wikicode。

  • Markdown 是本网站问题/评论中使用的格式。
  • BBCode在很多论坛软件等中以各种形式使用。
  • Wikicode 是 Wikipedia 和其他 Wiki 站点使用的标记代码。

解析器可用于 PHP 中的所有这些,以及其他语言。

例如,PHP 的 PECL 库中提供了一个 BBCode 解析器——请参见此处: http: //php.net/manual/en/book.bbcode.php。如果您能够将 PECL 库安装到您的服务器上,您可以在您的 PHP 中获得这些 BBCode 解析函数,而无需在运行时包含任何内容。

如果你不能走 PECL 路线,其他 BBCode 解析器也存在:试试这个,例如: http: //nbbc.sourceforge.net/

Wiki 标记解析器:Wikipedia 使用哪个 Wiki 标记解析器?

降价解析器: http: //michelf.com/projects/php-markdown/

希望有帮助。

于 2012-06-11T22:07:20.770 回答
0

不是正则表达式,但是...:

$s = '<<News>>
Breaking news on Sunday.
Have been taking hostages.
<<General Information>>
We would want to recieve our blabla.
And you want it.
<<User Suggestions>>
Yeah we want it so much...';

$s = str_replace('>>', '<H1>', $s);
$i = 1;
while (strpos($s, '<<') !== false)
{
    $s = str_replace_one('<<', '<H1 class="whatever" ID="Product_Header_' . $i . '">', $s);
    $i++;
}

function str_replace_one($find, $replace, $subject) 
{
    return implode($replace, explode($find, $subject, 2));
}


echo $s;
于 2012-06-11T22:05:03.150 回答
0

为什么不使用 preg_replace_callback 呢?

preg_replace_callback('/<<([^>]+)>>/', function($match) {
    static $key=0;
    $html = (($key > 0) ? '<br>-!-' : '') . '<H1 class="whatever" ID="Product_Header_'.$key.'">'.$val.'</H1>';
    $key++;
    return $html;
});
于 2012-06-11T22:09:26.620 回答