PHP:preg_replace仅替换数组中的第一个匹配字符串

时间:2018-11-25 13:08:31

标签: php arrays string preg-replace preg-split

我从PHP中的preg_replace开始,我想知道如何只将第一个匹配的数组键替换为指定的数组值,因为我将preg_replace的changes参数设置为'1',并且无论如何它都会更改多次。我也将字符串拆分为单个单词,并且正在逐一检查它们:

<?php
  $internal_message = 'Hey, this is awesome!';

  $words = array(
     '/wesome(\W|$)/' => 'wful',
     '/wful(\W|$)/' => 'wesome',
     '/^this(\W|$)/' => 'that',
     '/^that(\W|$)/' => 'this'
  );

  $splitted_message = preg_split("/[\s]+/", $internal_message);
  $words_num = count($splitted_message);

  for($i=0; $i<$words_num; $i++) {
     $splitted_message[$i] = preg_replace(array_keys($words), array_values($words), $splitted_message[$i], 1);
  }

  $message = implode(" ", $splitted_message);
  echo $message;
?>

我希望它在输出中显示:

  

嘿,太糟糕了

(更改一个后缀,更改一个单词并停止)

不是这样的:

  

嘿,太棒了

(两个后缀更改,两个词更改并返回原始词和后缀...)

也许我可以简化这段代码?我也无法更改数组键和值的顺序,因为很快就会有更多的后缀和单个单词更改。我是php编码的新手,感谢您的帮助;>

1 个答案:

答案 0 :(得分:0)

您可以在用于创建动态正则表达式模式的关联数组键中使用纯文本,并使用preg_replace_callback一次用替换项替换找到的值。

$internal_message = 'Hey, this is awesome!';

$words = array(
    'wesome' => 'wful',
    'wful' => 'wesome',
    'this' => 'that',
    'that' => 'this'
);
$rx = '~(?:' . implode("|", array_keys($words)) . ')\b~';
echo "$rx\n";
$message = preg_replace_callback($rx, function($m) use ($words) {
    return isset($words[$m[0]]) ? $words[$m[0]] : $m[0];
}, $internal_message);
echo $message;
// => Hey, that is awful!

请参见PHP demo

正则表达式为

~(?:wesome|wful|this|that)\b~

(?:wesome|wful|this|that)是一个不包含任何内部值的捕获组,而\b是一个单词边界,它是一种无消耗模式,可确保没有字母,数字或{{ 1}}。

_解析一次字符串,当匹配发生时,它将与preg_replace_callback数组(function($m))一起传递给匿名函数($words)。如果use ($words)数组包含找到的键($words),则返回对应的值(isset($words[$m[0]])),否则返回找到的匹配项($words[$m[0]])。