如何跳过strrpos Entry

Is it possible to skip a strpos/strrpos position?

    $string = "This is a cookie 'cookie'.";
    $finder = "cookie";
    $replacement = "monster";
    if (strrpos($string, $finder) !== false)
        str_replace($finder, $replacement, $string);

I want to skip the 'cookie' and replace the plain cookie so it'll result in "This is a monster 'cookie'."

I don't have qualms with it finding 'cookie' first and then checking it (Obviously necessary to determine it shouldn't be replaced), but I want to make sure that while 'cookie' is still there, I can use the same function to find the unquoted cookie.

Alternatively, is there a function I haven't found yet (Through hours of searching) to get all indices of a particular word so I can check them all through a loop without the use of regex?

It's important that it's the index, not the word itself, as there are other checks that have to be done based on where in the string the word's located.

The following gives the required replacement as well as the position of the replaced word.

$string = "This is a cookie 'cookie'."; 
$finder = "cookie";
$replacement = "monster";
$p = -1; // helps get position of current word
$position = -1; // the position of the word replaced
$arr = explode(' ',$string);
for($i = 0; $i < count($arr); $i += 1){
// Find the position $p of each word and
// Catch $position when a replacement is made
if($i == 0){$p = 0;} else {  $w =$arr[$i - 1]; $p  += strlen($w) + 1;}
if($arr[$i] == $finder){ if($position < 0){$position = $p;}$arr[$i] = $replacement;}}
$newstring = implode(' ', $arr);
echo $newstring; // gives: This is a monster 'cookie'
echo '<br/>';
echo $position;  // gives 10, the position of replaced element.

For the position, the assumption is that the sentence has only single spaces because spaces are used in the explode and implode functions. Otherwise a case of double or larger spaces would require modifications, possibly by replacing spaces with a unique character or set of characters such as @$# which would be used as the first argument of the explode and implode functions.

The code could be modified to capture more than one replacement, e.g. by capturing each replaced position in an array instead of testing for if(position < 0). This would also require to change the way $position is computed because its values are affected by the lengths of previous replacements.

You can try a regex instead:

Try the following:

$string = "This is a cookie 'cookie'.";

var_dump(preg_replace("/(?<!')(cookie)/", ' monster', $string));

This uses preg_replace instead of str_replace to replace the string.

Edit: You can use preg_match to get the position of the matched regex in the string like:

$string = "This is a cookie 'cookie'.";
$finder = "cookie";
preg_match("/(?<!')(" . preg_quote($finder) . ")/", $string, $matches, PREG_OFFSET_CAPTURE);
var_dump($matches);

And you can use preg_quote to make sure that preg_match and preg_replace doesn't treat the $finder var as a regex. And the difference in performance is very subtle between preg and other string functions in php. You can run some benchmarks to see how it varies in your case.

We can do also like this for short-hand :

Include also previous letter to function str_replace like this :

$string = "This is a cookie 'cookie'.";
echo str_replace('a cookie','a monster',$string);