2014-10-28 52 views
6

我试图从一个字符串创建共同的面具,像这样:如何替换字符串中的多个字符串而不重叠结果?

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 
+0

我在想重新排列数组,所以''dd'=>'{post}''处于不同的位置,但这引发了其他问题。 – 2014-10-28 20:28:26

+0

这不是我经常建议的正则表达式,但在这种情况下,它可能是谨慎的,所以你执行lookahead/behinds来检查你在替换之前的期望是什么 – 2014-10-28 20:34:30

+0

@scrowler不幸的是,我的PCRE库中有一个可变长度消极后台的bug。我无法升级PCRE库,因此我停止了这一步。 – Ryan 2014-10-28 20:48:04

回答

6

我可能会误解,但您似乎并不需要正则表达式来替换。它们很简单,直接替换。

$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()太棒了。它需要一个非常可读的输入,它不会像循环中的问题那样重新替换。

2

您可以使用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:(?![^{}]*})

哪个避免阵列的匹配关键字如果是因为封闭在{...}所有替换内容包含在{...}中。

+0

为什么'preg_replace'?为什么不'str_replace'或'strtr'?没有必要的regexing,是吗? – Rudie 2014-10-28 21:28:41

+0

如何在'str_replace'中使用前瞻? – anubhava 2014-10-28 21:31:05

+1

为什么你需要lookahead?它们是字面替换...源字符串中没有'{'和'}'。 – Rudie 2014-10-28 21:33:05

0

这将按顺序搜索每个替换字符串。如果它找到一个,它将分割字符串,并搜索字符串的其余部分以进行其他替换。

$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 

它将按照您指定的顺序进行搜索和查找。

相关问题