如何在不重叠结果的情况下替换字符串中的多个字符串?

时间:2021-01-04 09:09:55

I'm trying to create common masks from a string like so:

我正在尝试从字符串创建常见的掩码,如下所示:

012abc.d+e_fg~hijk => 012{start}.d+{middle}_fg~{end}jk

replace:

更换:

$arrFromTo = array(
              'st' => '{pre}',
              'abc' => '{start}',
              'e' => '{middle}',
              'hi' => '{end}',
              'dd' => '{post}'
             );

Instead I keep overlapping replacements and get something like this instead (using a loop of str_replace's):

相反,我保持重叠的替换,并得到这样的东西(使用str_replace的循环):

012{{pre}art}.d+{mi{post}le}_fg~{end}jk

Because the st is found in the already replaced {start} and dd is found in {middle}.

因为st已在已经替换的{start}中找到,而dd在{middle}中找到。

How would you replace the following?

你会如何取代以下?

$str = 'abc.d+e_fg~hijk';

echo replace_vars($str); // Desired output: 012{start}.d+{middle}_fg~{end}kJ

3 个解决方案

#1


6  

I might misunderstand, but you don't seem to need regex for the replacing. They're simple, literal replacements.

我可能会误解,但你似乎不需要正则表达式替换。它们是简单的,字面上的替代品。

$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() is awesome. It takes a very readable input and it doesn't re-replace like your problem in the loop.

strtr()太棒了。它需要一个非常易读的输入,它不会像循环中的问题那样重新替换。

#2


2  

You can use preg_replace like this:

您可以像这样使用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

Core of this regex is this negative lookaead: (?![^{}]*})

这个正则表达式的核心是这个负面看法:(?![^ {}] *})

Which avoid matching keys of array if it is enclosed in {...} since all the replacements are enclosed in {...}.

因为所有替换都包含在{...}中,所以避免匹配数组的键,如果它被包含在{...}中。

#3


0  

This will search the string for each replacement in order. If it finds one, it will split the string, and search the remainder of the string for any other replacements.

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

$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

It will search and find them in the order that you have specified.

它将按您指定的顺序搜索和查找它们。

#1


6  

I might misunderstand, but you don't seem to need regex for the replacing. They're simple, literal replacements.

我可能会误解,但你似乎不需要正则表达式替换。它们是简单的,字面上的替代品。

$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() is awesome. It takes a very readable input and it doesn't re-replace like your problem in the loop.

strtr()太棒了。它需要一个非常易读的输入,它不会像循环中的问题那样重新替换。

#2


2  

You can use preg_replace like this:

您可以像这样使用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

Core of this regex is this negative lookaead: (?![^{}]*})

这个正则表达式的核心是这个负面看法:(?![^ {}] *})

Which avoid matching keys of array if it is enclosed in {...} since all the replacements are enclosed in {...}.

因为所有替换都包含在{...}中,所以避免匹配数组的键,如果它被包含在{...}中。

#3


0  

This will search the string for each replacement in order. If it finds one, it will split the string, and search the remainder of the string for any other replacements.

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

$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

It will search and find them in the order that you have specified.

它将按您指定的顺序搜索和查找它们。