arrays - Php replace exact mach split

I have tried php replace but it changes all occurance. I want exact mach only and split | and +

$menu='home|about|product+service+able|contact|ab|';

echo str_replace("ab","book",$menu);

Result:

$result ='home|about|product+service+abel|contact|book|';

Or If example 2

$menu2='home|about|product+service+ab|contact|able|';

Result2

$result ='home|about|product+service+book|contact|able|';

Answer

Solution:

You have to use regular expression to catch 'ab' the the beginning and end of the string https://www.php.net/manual/ro/function.preg-replace.php see code below with some testcases

<?php
$menu='home|about|product+service+able|contact|ab|';
$menu1='home|about|product+service+able|contact|ab';
$menu2='ab|about|product+service+able|contact|abx|';
$menu3='home|ab|product+service+able|contact|abx';
$menu4='home|about|product+service+ab|contact|able|';

$pattern = array('/^ab([|+])/', '/([|+])ab([|+])/', '/([|+])ab$/');
$replacement = array('book${1}', '${1}book${2}', '${1}book');

echo preg_replace($pattern, $replacement, $menu);
echo "\n";

echo preg_replace($pattern, $replacement, $menu1);
echo "\n";

echo preg_replace($pattern, $replacement, $menu2);
echo "\n";

echo preg_replace($pattern, $replacement, $menu3);
echo "\n";

echo preg_replace($pattern, $replacement, $menu4);
echo "\n";

?>

output

home|about|product+service+able|contact|book|
home|about|product+service+able|contact|book
book|about|product+service+able|contact|abx|
home|book|product+service+able|contact|abx
home|about|product+service+book|contact|able|

Answer

Solution:

Since no one offered a non-regex solution, here is mine:

<?php
// Some Configuration
$searchFor = 'ab';
$replaceWith = 'book';

// Sample data
$menu = 'home|about|product+service+able|contact|ab|';

// Actual code
$array = explode('|', $menu);
$resultArray = [];
foreach ($array as $string) {
    if ($string === $searchFor) {
        $resultArray[] = $replaceWith;
    } else {
        $resultArray[] = $string;
    }
}
$result = implode('|', $resultArray);

echo $result;
// home|about|product+service+able|contact|book

You could make some optimizations, but for easier understanding i left it as it is.

Update: If you also want to be able to split between |+ too use the following.

<?php
function customSplit($var, $searchFor, $replaceWith) {
    $array = explode('|', $var);
    $resultArray = [];
    foreach ($array as $string) {
        $tmpResult = [];
        foreach (explode('|+', $string) as $tmpString) {
            if ($tmpString === $searchFor) {
                $tmpResult[] = $replaceWith;
            } else {
                $tmpResult[] = $tmpString;
            }
        }
        $resultArray[] = implode('|+', $tmpResult);
    }
    return implode('|', $resultArray);
}

// Some Configuration
$searchFor = 'ab';
$replaceWith = 'book';

// Sample data
$menu = 'home|about|product|+service|+able|contact|ab|';
$menu2 = 'home|about|product|+service|+ab|contact|able|';

echo customSplit($menu, $searchFor, $replaceWith);
// home|about|product|+service|+able|contact|book|

echo customSplit($menu2, $searchFor, $replaceWith);
// home|about|product|+service|+book|contact|able|

Answer

Solution:

Look for any ab not preceded or followed by a character in the range a-z.

So you need a negative lookbehind for a-z : (?<![a-z])

and a negative look ahead for a-z : (?![a-z])

with ab in the middle

regex: (?<![a-z])ab(?![a-z])

Here is an example

And in php:

$pattern = '/(?<![a-z])ab(?![a-z])/';
$result  = preg_replace($pattern,'book',$yourstring);

Answer

Solution:

function make more easier

function replace_match($find, $replace, $menu)
{
    $pattern = array('/^'.$find.'([|+])/', '/([|+])'.$find.'([|+])/', '/([|+])'.$find.'$/');
    $replacement = array($replace.'${1}', '${1}'.$replace.'${2}', '${1}'.$replace); 
    return preg_replace($pattern, $replacement, $menu);
}

echo replace_match('ab','book',$menu);

Source