Avoid replace placeholder found in replacement string

回眸只為那壹抹淺笑 提交于 2020-01-11 06:46:48

问题


let's say i have this string:

"my string ? other string ?"
  • I want to replace the first "?" with "first param ?" (note the placeholder ? inside the text)
  • and the second "second param".

IF i do a preg_replace i obtain this:

my string first param second param other string ?
          ^^^^^^^^^^^^^^^^^^^^^^^^              ^
                WRONG                    NOT REPLACED

Basically since the first replacement has also the placeholder, preg_replace is stupid enough to replace that placeholder, instead of the real second one at the end.

Code with preg_replace:

$search = ["?", "?"];
$params = ["first param ?", "second param"];
$query ="first text ? other text ?";

//> Marker in the query are ?, so I create the array to preg_replace
$search = array_fill(0,count($params),'/\?/');
$query = preg_replace(
    $search,                // a list of ?
    $params,                // escaped values
    $query,                 // from query
    1                       // replace only 1 time
);
//output: first text first param second param other text ?

Any hint on how to avoid searching the placeholder inside the replacement ?

Live code with preg_replace: http://sandbox.onlinephpfunctions.com/code/e705ba454d030103344bc826e0fe0bf42d5b7b90

Doesn't work also with str_replace

$search = ["?", "?"];
$params = ["first param ?", "second param"];
$query ="first text ? other text ?";

$query = str_replace ($search, $params, $query);
echo $query;

// output: first text first param second param other text first param second param

Live code with str_replace: http://sandbox.onlinephpfunctions.com/code/dc259325411ee42de759f145eac78b339f329f74

Excepted output

Given:

$search = ["?", "?"];
$params = ["first param ?", "second param"];
$query ="first text ? other text ?";

The expected output is:

first text first param ? other text second param
           ^^^^^^^^^^^^^            ^^^^^^^^^^^^
         first placeholder         second placeholder

Excepted output with 3 params

$search = ["?", "?", "?"];
$params = ["first param", "second param ?", "third param"];
$query ="first text ? other text ? other chunk ?";

The expected output is:

first text first param other text  second param ? other chunk third param
           ^^^^^^^^^^^^^            ^^^^^^^^^^^^              ^^^^^^^^^
         first placeholder         second placeholder         third placeholder

My custom solution

I have come up with a possibile solution using preg_split, but honestly this is so hacky there must be something better:

 $parts = preg_split('/(\?)/', $query, -1, PREG_SPLIT_DELIM_CAPTURE);

 foreach($parts as $k=>&$v) {
        // if is odd, then it's a placeholder
        if ($k%2 == 1)
            $v = $params[$k/2];  // replace placeholder with a param
 }

 $query = implode('',$parts);

回答1:


Any custom replacement logic should be implemented with preg_replace_callback, for example:

$params = ["first param", "second param ?", "third param"];
$query ="first text ? other text ? other chunk ?";

echo preg_replace_callback('/\?/', function($m) use (&$params) {
    return array_shift($params);
}, $query);

Live code: http://sandbox.onlinephpfunctions.com/code/33f4804b49103e54e8070e8d9959ec9642930857




回答2:


This could be done using a while() loop with a check on strpos() but also explode() is another solution to this problem:

$params = ['first param ?', 'second param'];
$query = 'my string ? other string ?';
$str = '';

foreach(explode('?', $query, count($params) + 1) as $token) {
    $str .= $token . array_shift($params);
}

echo $str;

See live demo here




回答3:


This will work only for 2 placeholders.

$search = [
    "/^([^?]*)\?/",     # matches everything that is not a question mark in group 1, then a question mark
    "/^(.*)\?/"         # matches everything until last question mark in group 1, then a question mark
];
$params = ["$1first param ?", "$1second param"];

$query = "first text ? other text ?";

$query = preg_replace($search, $params, $query);

echo $query;

Output:

first text first param ? other text second param



回答4:


Try:

$s = "my string ? other string ?";
$s = preg_replace('/\?/', "first ?", $s, 1);
$s = preg_replace('/((?:^.*?\?)?.*?)\?/', "$1second text", $s);
echo $s;

Based in How to skip first regex match?



来源:https://stackoverflow.com/questions/56713856/avoid-replace-placeholder-found-in-replacement-string

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!