6

I am parsing a string before sending it to a DB. I want to go over all <br> in that string and replace them with unique numbers that I get from an array followed by a newLine.

For example:

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"

Sounds simple enough. I would just do a while loop, get all the occurances of <br> using strpos, and replace those with the required numbers+\n using str_replace.

Problem is that I always get an error and I have no idea what I am doing wrong? Probably a dumb mistake, but still annoying.

Here is my code

$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++;
}

Any ideas please?

Thanks in advance,

1
  • Well first, of all in the first iteration you will replace all the instances of <br>.... To do it this way you would have to only replce parts of the string using substr_replace which lets you define the postions for he replacement. Commented Apr 22, 2013 at 16:44

6 Answers 6

8

I would use a regex and a custom callback, like this:

$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);

Note that this assumes we can modify the $replace array. If that's not the case, you can keep a counter:

$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);

You can see from this demo that this outputs:

Line 1 Line 2 Line 3 Line 4 
Sign up to request clarification or add additional context in comments.

6 Comments

You answer works and str is parsed correctly, but for some reason it is doesn't get inserted into the DB when I call INSERT INTO. Any ideas why?
@r3x - How come? Do you have an error message? If you're looking to print the literal \n characters instead of letting PHP interpret that to the newline character, change the double quotes around "\n" to single quotes.
Here is my insert query (interestTable is basically the parsed string). mysql_query("INSERT INTO $tbl_name(userID,storyID,rank, storyType, interestTable)VALUES('$userID','$storyID','$rank','$storyType','$interestTable')", $dbh1); If I delete the value of interestTable from this query then everything works fine, but if I add it nothing get sent. As for the error, I did not get any. Weird :S
I think that the string content is not formatted correctly. Even "Line 1 \nLine 2\nLine 3\nLine 4\n" are not inserted to the DB, so it is not a matter of size.
Without an error message or more information it's impossible to tell what's going wrong.
|
1

if you just want to count it, you can use this too.

$str_expl = explode('<br>',$str);
foreach($str_expl as $index=>&$str)
    if(!empty($str))
        $str .= ($index+1);
$str = implode($str_expl);

1 Comment

if you want to replace the found items with your own array, you can change str .= ($index+1) to str .= $myArray[index];
1
$str = str_replace('<br>', $replace[$index] . ' ' .'\n', $str);

This is replaces ALL the occurences of <br> it finds.

The correct is to only do one single replacement per iteration: substr_replace can replace one single part of a string. Correct would be:

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++;
}

(Don't forget the $ before the replaceIndex! $replaceIndex is a variable)

1 Comment

The 4th parameter to str_replace is not how many times to replace. It's a reference that's set to how many time it did replace.
0

You need to remember the $ in front of variables. Also, try using the php regex function, which allows specifying the number of replacements.

<?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
?>

5 Comments

The last parameter does not let you set the number of replacements. It's a reference that's set to the number of replacements it did do.
I am referring to the $limit variable in preg_replace.
I thought you were using the $count parameter. Never mind :-)
Ah, I see you were responding to the answer directly below mine!
This requires N regexes to be applied on the string, which can kill performance if the string contains a lot of <br> elements.
0

Here's my version. 8 formatted lines, no regex, KISS.

$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;

Comments

0

The preg_replace_callback will help you manipulate the replacement process, and nickb's answer shows how it can be done.

However, there can be more matches than the amount of items in the $replace array. If you want to re-start using its elements from the 0th item, you need to reset the counter once it is equal to the $replace array size.

See the PHP demo:

$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;

Output: Line 1 Line 2 Line 3 Line 4 Line 1 Line 2.

Note that the <br\s*/?> regex matches br tags that can be self-closing (/? matches an optional / char, and in order to keep / unescaped in the pattern, I used the ~ char as a regex delimiter) and that may contain zero or more whitespaces (\s*) after br and before /> / >.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.