避免替换在替换字符串中找到的占位符
Avoid replace placeholder found in replacement string
假设我有这个字符串:
"my string ? other string ?"
- 我想替换第一个“?” with
"first param ?"
(注意文本中的占位符 ?)
- 和第二个
"second param".
如果我做 preg_replace 我得到这个:
my string first param second param other string ?
^^^^^^^^^^^^^^^^^^^^^^^^ ^
WRONG NOT REPLACED
基本上因为第一个替换也有占位符,preg_replace
愚蠢到替换那个占位符,而不是最后真正的第二个。
代码 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 ?
关于如何避免在替换中搜索占位符的任何提示?
带 preg_replace
的实时代码:http://sandbox.onlinephpfunctions.com/code/e705ba454d030103344bc826e0fe0bf42d5b7b90
不适用于 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
使用 str_replace 的实时代码:
http://sandbox.onlinephpfunctions.com/code/dc259325411ee42de759f145eac78b339f329f74
异常输出
给定:
$search = ["?", "?"];
$params = ["first param ?", "second param"];
$query ="first text ? other text ?";
预期输出为:
first text first param ? other text second param
^^^^^^^^^^^^^ ^^^^^^^^^^^^
first placeholder second placeholder
带有 3 个参数的异常输出
$search = ["?", "?", "?"];
$params = ["first param", "second param ?", "third param"];
$query ="first text ? other text ? other chunk ?";
预期输出为:
first text first param other text second param ? other chunk third param
^^^^^^^^^^^^^ ^^^^^^^^^^^^ ^^^^^^^^^
first placeholder second placeholder third placeholder
我的自定义解决方案
我使用 preg_split
提出了一个可能的解决方案,但老实说,这太老套了,必须有更好的方法:
$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);
这仅适用于 2 个占位符。
$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 = ["first param ?", "second param"];
$query = "first text ? other text ?";
$query = preg_replace($search, $params, $query);
echo $query;
输出:
first text first param ? other text second param
尝试:
$s = "my string ? other string ?";
$s = preg_replace('/\?/', "first ?", $s, 1);
$s = preg_replace('/((?:^.*?\?)?.*?)\?/', "second text", $s);
echo $s;
基于How to skip first regex match?
任何自定义替换逻辑都应使用 preg_replace_callback
实现,例如:
$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);
实时代码:http://sandbox.onlinephpfunctions.com/code/33f4804b49103e54e8070e8d9959ec9642930857
这可以使用 while()
循环并检查 strpos()
来完成,但 explode()
也是解决此问题的另一种方法:
$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;
假设我有这个字符串:
"my string ? other string ?"
- 我想替换第一个“?” with
"first param ?"
(注意文本中的占位符 ?) - 和第二个
"second param".
如果我做 preg_replace 我得到这个:
my string first param second param other string ?
^^^^^^^^^^^^^^^^^^^^^^^^ ^
WRONG NOT REPLACED
基本上因为第一个替换也有占位符,preg_replace
愚蠢到替换那个占位符,而不是最后真正的第二个。
代码 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 ?
关于如何避免在替换中搜索占位符的任何提示?
带 preg_replace
的实时代码:http://sandbox.onlinephpfunctions.com/code/e705ba454d030103344bc826e0fe0bf42d5b7b90
不适用于 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
使用 str_replace 的实时代码: http://sandbox.onlinephpfunctions.com/code/dc259325411ee42de759f145eac78b339f329f74
异常输出
给定:
$search = ["?", "?"];
$params = ["first param ?", "second param"];
$query ="first text ? other text ?";
预期输出为:
first text first param ? other text second param
^^^^^^^^^^^^^ ^^^^^^^^^^^^
first placeholder second placeholder
带有 3 个参数的异常输出
$search = ["?", "?", "?"];
$params = ["first param", "second param ?", "third param"];
$query ="first text ? other text ? other chunk ?";
预期输出为:
first text first param other text second param ? other chunk third param
^^^^^^^^^^^^^ ^^^^^^^^^^^^ ^^^^^^^^^
first placeholder second placeholder third placeholder
我的自定义解决方案
我使用 preg_split
提出了一个可能的解决方案,但老实说,这太老套了,必须有更好的方法:
$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);
这仅适用于 2 个占位符。
$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 = ["first param ?", "second param"];
$query = "first text ? other text ?";
$query = preg_replace($search, $params, $query);
echo $query;
输出:
first text first param ? other text second param
尝试:
$s = "my string ? other string ?";
$s = preg_replace('/\?/', "first ?", $s, 1);
$s = preg_replace('/((?:^.*?\?)?.*?)\?/', "second text", $s);
echo $s;
基于How to skip first regex match?
任何自定义替换逻辑都应使用 preg_replace_callback
实现,例如:
$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);
实时代码:http://sandbox.onlinephpfunctions.com/code/33f4804b49103e54e8070e8d9959ec9642930857
这可以使用 while()
循环并检查 strpos()
来完成,但 explode()
也是解决此问题的另一种方法:
$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;