PHP preg_replace里面的for循环

时间:2014-04-13 17:30:57

标签: php for-loop preg-replace

我目前正在尝试这个PHP preg_replace功能,但我遇到了一个小问题。我想用带有ID的div替换所有标签,每个div都是唯一的,所以我想我会把它添加到for循环中。但是以某种奇怪的方式,它只执行第一行并给它一个49的ID,这是他们可以获得的最后一个ID。这是我的代码:

$res = mysqli_query($mysqli, "SELECT * FROM song WHERE id = 1");
$row = mysqli_fetch_assoc($res);
mysqli_set_charset("utf8");

$lyric = $row['lyric'];
$lyricHTML = nl2br($lyric);

$lines_arr = preg_split('[<br />]',$lyricHTML);
$lines = count($lines_arr); 

for($i = 0; $i < $lines; $i++) {
    $string = preg_replace(']<br />]', '</h4><h4 id="no'.$i.'">', $lyricHTML, 1);
    echo $i;
}

echo '<h4>';
echo $string;
echo '</h4>';

它的工作原理是我的数据库中有大量的文本,当我将它添加到lyric变量中时,它只是纯文本。但是当我知道它时,它会在每一行之后得到它,我在这里使用它。我通过使用小&#34; lines_arr&#34;得到了数量。你可以看到的方法,然后基本上迭代for循环。

唯一的问题是它只在第一行输出并且给出了49的ID。当我将它移到for循环之外并删除限制时,它可以工作,并且所有行都围绕它们获得<h4> ,但后来我没有得到我需要的唯一ID。

这是我从数据库中提取的一些文字

Mama called about the paper turns out they wrote about me Now my broken heart´s the only thing that's broke about me So many people should have seen what we got going on I only wanna put my heart and my life in songs Writing about the pain I felt with my daddy gone About the emptiness I felt when I sat alone About the happiness I feel when I sing it loud He should have heard the noise we made with the happy crowd Did my Gran Daddy know he taught me what a poem was How you can use a sentence or just a simple pause What will I say when my kids ask me who my daddy was I thought about it for a while and I'm at a loss Knowing that I´m gonna live my whole life without him I found out a lot of things I never knew about him All I know is that I´ll never really be alone Cause we gotta lot of love and a happy home

我的目标是为每一行提供一个<h4 id="no1">TEXT</h4>no之后的数字,如no1no4应该每次迭代递增,&# 39;为什么我选择了for-loop。

3 个答案:

答案 0 :(得分:2)

看起来你需要逃避你的正则表达式

 preg_replace('/\[<br \/\]/', ...);

但实际上,这是一个经典的XY Problem。您应该问我们如何解决您的问题,而不是问我们如何解决您的解决方案。

向我们展示数据库中的一些示例文本,然后向我们展示您希望如何格式化它。它很可能是更好的方式。


我会使用array_walkideone demo here

$lines = preg_split("/[\r\n]+/", $row['lyric']);

array_walk($lines, function(&$line, $idx) {
  $line = sprintf("<h4 id='no%d'>%s</h4>", $idx+1, $line);
});

echo implode("\n", $lines);

输出

<h4 id="no1">Mama called about the paper turns out they wrote about me</h4>
<h4 id="no2">Now my broken heart's the only thing that's broke about me</h4>
<h4 id="no3">So many people should have seen what we got going on</h4>
...
<h4 id="no16">Cause we gotta lot of love and a happy home</h4>

解决方案的解释

nl2br在这里并没有真正帮助我们。它会将\n转换为<br />,但之后我们才会最终将字符串拆分为br。我们也可以先使用\n进行拆分。我将使用/[\r\n]+/,因为它会拆分一个或多个\r\n\r\n

    $lines = preg_split("/[\r\n]+/", $row['lyric']);

现在我们有一个字符串数组,每个字符串包含一行歌词。但我们希望将每个字符串包装在<h4 id="noX">...</h4>中,其中X是该行的编号。

通常我们会使用array_map,但array_map回调不会收到索引参数。相反,我们将使用确实接收索引的array_walk

关于这一行的另一个注意事项是使用&$line作为回调参数。这允许我们改变$line的内容并将其保存为#34;在我们原来的$lyrics数组中。 (参见PHP文档中的示例#1来比较差异)。

    array_walk($lines, function(&$line, $idx) {

这里是h4的来源。我使用sprintf来格式化HTML字符串,因为我认为它们更具可读性。它允许您控制参数的输出方式,而无需在&#34;模板中添加一堆视图逻辑。

这是世界上最小的模板:'<h4 id="no%d">%s</h4>'。它有两个输入%d%s。第一个将作为数字(我们的行号)输出,第二个将作为字符串输出(我们的歌词)。

      $line = sprintf('<h4 id="no%d">%s</h4>', $idx+1, $line);

关闭array_walk回调函数

    });

现在$lines是我们新格式化歌词的数组。让我们通过用\n分隔每一行来输出歌词。

    echo implode("\n", $lines);

完成!

答案 1 :(得分:1)

如果db中的文本在每行中,为什么不用\ n字符爆炸它?

总是尝试在不使用preg功能集的情况下找到解决方案,因为它们是重度内存使用者:

我会去看看:

$lyric = $row['lyric'];

$lyrics =explode("\n",$lyrics);
$lyricsHtml=null;
$i=0;
foreach($lyrics as $val){
$i++;
$lyricsHtml[] = '<h4 id="no'.$i.'">'.$val.'</h4>';
} 
$lyricsHtml = implode("\n",$lyricsHtml);

答案 2 :(得分:1)

preg_replace_callback的另一种方式:

$id = 0;
$lyric = preg_replace_callback('~(^)|$~m',
    function ($m) use (&$id) {
        return (isset($m[1])) ? '<h4 id="no' . ++$id . '">' : '</h4>'; },
    $lyric);