【问题标题】:preg_replace: how to consider whole array of patterns before replacing?preg_replace:在替换之前如何考虑整个模式数组?
【发布时间】:2023-03-15 06:58:01
【问题描述】:

我正在使用preg_replace 来匹配编码不正确的 UTF-8 字符并将其替换为正确的字符。我创建了一个包含错误字符的“旧”数组,以及一个带有替换的相应“新”数组。这是每个数组的一个sn-p:

$old = array(
  '/â€/',
  '/’/',
);
$new = array(
  '†',
  '’',
);

注意:如果你对我这样做的原因感到好奇,read more here

可能包含错误数据的示例字符串可能是:

The programmer’s becoming very frustrated

应该变成:

The programmer's becoming very frustrated

我正在使用这个功能:

$result = preg_replace($old, $new, $str);

但主题实际上正在变成:

The programmer†™s becoming very frustrated

很明显,PHP 正在对该主题进行我所说的非贪婪匹配(我知道,这里使用的术语不正确)。 preg_replace 正在对旧/新数组中的第一对执行替换,而不考虑模式数组中是否可能存在更合适的不同模式。如果我颠倒替换对的顺序,那么它会按预期工作。

我的问题是:有没有一种方法可以让preg_replace 在执行替换之前考虑模式数组的所有元素,还是我唯一的选择是重新排序数组?

【问题讨论】:

    标签: php regex preg-replace


    【解决方案1】:

    我认为没有这样的选择。但是,您可以使用关联数组来存储您的替换并使用uasortstrlen 对其进行排序,因此更大的匹配会首先出现,您无需手动管理数组顺序。

    然后,您可以使用 array_keysarray_values 来像分开的 $old$new 数组一样操作。

    $replacements = array(
        '†' => '/â€/',
        '’' => '/’/',
    );
    
    // sorts the replacements array by value string length keeping the indexes intact
    uasort($replacements, function($a, $b) {
        return strlen($b) - strlen($a);
    });
    
    $str = 'The programmer’s becoming very frustrated';
    $result = preg_replace(array_values($replacements), array_keys($replacements), $str);
    

    编辑:正如@CasimiretHippolyte 指出的那样,在这种情况下,preg_replace 函数的第一个参数不需要使用array_values。它只会从 $replacements 返回带有数字索引的副本,但顺序是相同的。除非您需要一个与您的问题中的$old 具有相同结构的数组,否则您不需要使用它。

    【讨论】:

      【解决方案2】:

      对数组$old$new 进行排序,使最长的正则表达式排在第一位:

      $old = array(
        '/’/',
        '/â€/',
      );
      $new = array(
        '’',
        '†',
      );
      $str = 'The programmer’s becoming very frustrated';
      $result = preg_replace($old, $new, $str);
      echo $result,"\n";
      

      输出:

      The programmer’s becoming very frustrated
      

      【讨论】:

        【解决方案3】:

        我不相信只有使用preg_replace 才能做到这一点。但是,您可以轻松地预先对数组进行排序:

        $replacements = array_combine($old, $new);
        krsort($replacements);
        $result = preg_repalce( array_keys($replacements), array_values($replacements), $string);
        

        【讨论】:

          猜你喜欢
          • 2017-12-21
          • 2013-02-24
          • 2011-09-27
          • 1970-01-01
          • 2016-06-17
          • 1970-01-01
          • 2012-03-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多