用数组中的值替换字符串中所有出现的内容

6
我正在解析一个字符串,然后将其发送到数据库。我想查找该字符串中的所有<br>,并用来自数组的唯一数字替换它们,然后跟随一个新行。
例如:
str = "Line <br> Line <br> Line <br> Line <br>"
$replace = array("1", "2", "3", "4");

my function would return 
"Line 1 \n Line 2 \n Line 3 \n Line 4 \n"

听起来很简单。我只需使用while循环,使用strpos获取所有<br>的出现次数,并使用str_replace将其替换为所需的数字+\n。
问题是我总是会得到一个错误,而且我不知道我做错了什么?可能是一个愚蠢的错误,但仍然很烦人。
以下是我的代码。
$str     = "Line <br> Line <br> Line <br> Line <br>";
$replace = array("1", "2", "3", "4");
$replaceIndex = 0;

while(strpos($str, '<br>') != false )
{
    $str = str_replace('<br>', $replace[index] . ' ' .'\n', $str); //str_replace, replaces the first occurance of <br> it finds
    index++;
}

任何想法请?
先行感谢,

首先,在第一次迭代中,您将替换所有<br>的实例... 要以这种方式完成,您只需使用substr_replace替换字符串的部分,并定义替换的位置即可。 - prodigitalson
6个回答

8
我会使用正则表达式和自定义回调函数来实现,代码如下:
$str = "Line <br> Line <br> Line <br> Line <br>";
$replace = array("1", "2", "3", "4");
$str = preg_replace_callback( '/<br>/', function( $match) use( &$replace) {
    return array_shift( $replace) . ' ' . "\n";
}, $str);

请注意,这里假设我们可以修改$replace数组。如果不能修改,您可以保留一个计数器:
$str = "Line <br> Line <br> Line <br> Line <br>";
$replace = array("1", "2", "3", "4");
$count = 0;
$str = preg_replace_callback( '/<br>/', function( $match) use( $replace, &$count) {
    return $replace[$count++] . ' ' . "\n";
}, $str);

您可以从此演示中看到,它会输出:
Line 1 Line 2 Line 3 Line 4 

你的答案是正确的,str也被正确解析了,但是当我调用INSERT INTO时,它却没有被插入到数据库中。有什么想法吗? - r3x
@r3x - 怎么了?你有错误信息吗?如果你想打印字面上的\n字符而不是让PHP将其解释为换行符,那么请将围绕着"\n"的双引号改为单引号。 - nickb
这是我的插入查询(interestTable基本上是解析后的字符串)。mysql_query("INSERT INTO $tbl_name(userID,storyID,rank, storyType, interestTable)VALUES('$userID','$storyID','$rank','$storyType','$interestTable')", $dbh1);如果我从此查询中删除interestTable的值,那么一切都正常工作,但如果我添加它,则什么也不会发送。至于错误,我没有收到任何错误信息。奇怪:S - r3x
我认为字符串内容格式不正确。即使"Line 1 \nLine 2\nLine 3\nLine 4\n"都没有插入到数据库中,所以这不是大小的问题。 - r3x
没有错误消息或更多信息,就无法确定出了什么问题。 - nickb
原来是格式问题。(字符串中有一个 '。)你的代码没问题 :) - r3x

1
$str = str_replace('<br>', $replace[$index] . ' ' .'\n', $str);

这将替换掉所有出现的 <br>
正确的方法是每次迭代只进行一次替换: substr_replace 可以替换字符串的一个部分。正确的方法是:
while($pos = strpos($str, '<br>') !== false )
{
    $str = substr_replace($str, $replace[$replaceIndex] . ' ' .'\n', $pos, 4); // The <br> is four bytes long, so 4 bytes from $pos on.
    $replaceIndex++;
}

(在replaceIndex之前不要忘记$$replaceIndex是一个变量)


1
str_replace 的第四个参数并不是指要替换的次数,而是一个引用,用于记录实际替换的次数。 - gen_Eric

1
如果你只想计数,你也可以使用这个。
$str_expl = explode('<br>',$str);
foreach($str_expl as $index=>&$str)
    if(!empty($str))
        $str .= ($index+1);
$str = implode($str_expl);

如果您想用自己的数组替换找到的项目,可以将 str .= ($index+1) 更改为 str .= $myArray[index]; - ikkez

0

在变量前面记得加上$符号。此外,尝试使用php正则表达式函数,它允许指定替换的数量。

<?php
$str     = "Line <br> Line <br> Line <br> Line <br>";
$replace = array("1", "2", "3", "4");
$index = 0;
$count = 1;

while(strpos($str, '<br>') != false )
{
    $str = preg_replace('/<br>/', $replace[$index] . " \n", $str, 1); //str_replace, replaces the first occurance of <br> it finds
    $index++;
}
echo $str
?>

最后一个参数不允许您设置替换次数。它是一个引用,指向实际进行替换的次数。 - gen_Eric
我指的是preg_replace中的$limit变量。 - George
我以为你在使用$count参数。没关系 :-) - gen_Eric
啊,我看到你是在回答我的下面的答案! - George
如果字符串包含大量的<br>元素,那么需要对该字符串应用N个正则表达式,这可能会影响性能。 - nickb

0
这是我的版本。8个格式化行,没有正则表达式,简单易懂。
$str = "Line <br> Line <br> Line <br> Line <br>";
$replace = array("1", "2", "3", "4");

$temp = explode("<br>", $str);
$result = "";
foreach ($temp as $k=>$v) {
    $result .= $v;
    if ($k != count($temp) - 1) {
        $result .= $replace[$k];
    }
}

echo $result;

0

preg_replace_callback会帮助你操作替换过程,nickb的回答展示了如何完成。

然而,匹配项数量可能比$replace数组中的项数更多。如果你想从第0个元素重新开始使用它的元素,则需要在计数器等于$replace数组大小时重置计数器。

请参见PHP演示

$text = "Line <br> Line <br> Line <br> Line <br> Line <br> Line <br>";
$replace = array("1", "2", "3", "4");
$counter = 0;
$text = preg_replace_callback('~<br\s*/?>~', function($m) use($replace, &$counter) {
    if ($counter === count($replace)) { $counter = 0; }
    return $replace[$counter++];
}, $text);
echo $text;

输出:行1 行2 行3 行4 行1 行2

请注意,<br\s*/?> 正则表达式匹配可以是自闭合的 br 标签(/? 匹配可选的 / 字符,并为了让 / 在模式中不被转义,我使用了 ~ 字符作为 正则表达式定界符),并且在 br/> / > 之间可能包含零个或多个空格字符(\s*)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接