问题
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