Как я могу заменить несколько строк в строке без перекрытия результатов?
Я пытаюсь создать общие маски из строки, например:
012abc.d+e_fg~hijk => 012{start}.d+{middle}_fg~{end}jk
заменить:
$arrFromTo = array(
'st' => '{pre}',
'abc' => '{start}',
'e' => '{middle}',
'hi' => '{end}',
'dd' => '{post}'
);
вместо этого я продолжаю перекрывать замены и получаю что-то вроде этого (используя цикл str_replace
С):
012{{pre}art}.d+{mi{post}le}_fg~{end}jk
потому что st
находится в уже замененном {start}
и dd
находится в {middle}
.
как бы вы заменить?
$str = 'abc.d+e_fg~hijk';
echo replace_vars($str); // Desired output: 012{start}.d+{middle}_fg~{end}kJ
3 ответов
Я могу неправильно понять, но вам, похоже, не нужно регулярное выражение для замены. Это простая, буквальная замена.
$from = '012abc.d+e_fg~hijk';
$arrFromTo = array(
'st' => '{pre}',
'abc' => '{start}',
'e' => '{middle}',
'hi' => '{end}',
'dd' => '{post}'
);
$to = strtr($from, $arrFromTo); // 012{start}.d+{middle}_fg~{end}jk
strtr()
это круто. Он принимает очень читаемый ввод, и он не заменяет, как ваша проблема в цикле.
можно использовать preg_replace
такой:
$str = '012abc.d+e_fg~hijk';
$arrFromTo = array(
'st' => '{pre}',
'abc' => '{start}',
'e' => '{middle}',
'hi' => '{end}',
'dd' => '{post}'
);
$reArr=array();
foreach($arrFromTo as $k=>$v){
$reArr['/' . $k . '(?![^{}]*})/'] = $v;
}
echo preg_replace(array_keys($reArr), array_values($reArr), $str);
//=> 012{start}.d+{middle}_fg~{end}jk
ядро этого регулярного выражения-это отрицательный lookaead:(?![^{}]*})
которые избегают совпадающих ключей массива, если он заключен в {...}
так как все замены заключены в {...}
.
поиск строки для каждой замены. Если он найдет его, он разделит строку и будет искать оставшуюся часть строки для любых других замен.
$str = '012abc.d+e_fg~hijk';
$rep = array(
'st' => '{pre}',
'abc' => '{start}',
'e' => '{middle}',
'hi' => '{end}',
'dd' => '{post}'
);
$searched = '';
foreach ($rep as $key => $r) {
if (strpos($str, $key) !== false) {
$searched .= substr($str, 0, strpos($str, $key)) . $r;
$str = substr($str, strpos($str, $key) + strlen($key));
}
}
$searched .= $str;
echo $searched; //012{start}.d+{middle}_fg~{end}jk
он будет искать и находить их в указанном Вами порядке.