【问题标题】:PHP: preg_replace only first matching string in arrayPHP:preg_replace 仅数组中的第一个匹配字符串
【发布时间】:2018-11-25 13:08:31
【问题描述】:

我从 PHP 中的 preg_replace 开始,我想知道如何只用指定的数组值替换第一个匹配的数组键,因为我将 preg_replace 更改次数参数设置为“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 编码的新手,我会感谢任何帮助;>

【问题讨论】:

  • 试试this approach
  • Nvrmind,像魅力一样工作!谢谢;>
  • @WiktorStribiżew 特殊字符现在对我来说非常重要,没有它们我将无法使用这段代码做任何事情
  • 您应该从一开始就提到您正在使用 Unicode 文本,这是一个重要的细节。

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


【解决方案1】:

您可以在用于创建动态正则表达式模式的关联数组键中使用纯文本,并使用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 是单词边界,是确保后缀后没有字母、数字或 _ 的非消耗模式.

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

【讨论】:

  • 我还有一个问题,是否有任何选项可以在后缀末尾使用“ś”或“ć”等特殊字符?因为我看到像这些末尾带有字母的后缀没有被更改。
  • @ThatsJames 当然,只需使用 u 修饰符 $rx = '~(?:' . implode("|", array_keys($words)) . ')\b~u';
  • 非常感谢,很抱歉之前没有提到这个细节。
猜你喜欢
  • 1970-01-01
  • 2015-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多