【问题标题】:Using preg_replace to make ordinals appear in all lower case使用 preg_replace 使序数全部小写
【发布时间】:2013-09-06 12:03:47
【问题描述】:

我有一列地址数据,其序号显示如下:

坎布里亚楼 3 楼

2楼223室

当我希望它们改为这样显示时:

坎布里亚楼 3 楼

2楼223室

我正在尝试使用 preg_replace 函数来换出一个大写字母,它直接跟在一个数字之后,而是用一个小写字母代替。 (我承认这是我第一次使用 preg_replace 函数。但是我对 preg_match 和正则表达式很好)。

到目前为止我有:

$string = '3Rd Floor, Cumbrian House';

$ordinalregex = '/(^.*\d+)([A-Z])/';
$correctordinal = '$1'.strtolower('$2');

echo preg_replace($ordinalregex,$correctordinal,$string)."<br>";

但它没有达到预期的效果,并完全按照它最初出现的方式输出。

谢谢

【问题讨论】:

  • 您的示例代码中缺少输入字符串定义。此外,对于您概述的情况,代码看起来有点多。请把它减少到一个最小的例子,例如从头开始重写它以隔离唯一的问题。
  • 另外你为什么不能使用strtr并将3Rd替换为3rd2Nd替换为2nd
  • @hakre 因为我需要一个包罗万象的解决方案,所以当地址有第 4 个、第 9 个等时,我不必逐个写替换......它也应该能够处理平面地址,因此 239A 变为 239a。
  • 嗯,会不会是事先对数据应用了一些错误的方法?可能有点晚了,但最好一开始就阻止它。为此,了解环视通常很有帮助:regular-expressions.info/lookaround.html

标签: php string case-sensitive


【解决方案1】:

我认为您需要使用preg_replace_callback,因为我不确定您是否可以根据您在普通 preg_replace 中匹配的部分进行替换。您需要做的是使用一个回调函数来获取匹配数组并对其进行处理(您也可以只使用 preg_match,然后单独使用匹配项)。

此示例有效(尽管它使用匿名函数进行回调,需要 PHP 5.3.0+):

function fixOrdinals($string) { 
    return preg_replace_callback("/[0-9][A-Z]/",
        function ($matches) { 
            return strtolower($matches[0]);
        },
        $string
    );
}

echo fixOrdinals("3Rd Floor, Cumbrian House")."\n";
echo fixOrdinals("Room 223, 2Nd Floor")."\n";
echo fixOrdinals("4Th Room, 2Nd Floor")."\n";

输出:

3rd Floor, Cumbrian House
Room 223, 2nd Floor
4th Room, 2nd Floor

【讨论】:

  • 这对我来说似乎是最好的解决方案。我之前没有遇到过 $matches 数组的概念或匿名函数的概念,但我可以看到他们在做什么,并将相同的原则应用于其他地址异常,例如 'O'Reilly' 保持 O'Reilly 身份“圣约翰”应该是圣约翰。谢谢
【解决方案2】:
<?php

    $ordinalregex = '/(\d+)(st|nd|rd|th)/ei';
    $input = "Room 223, 2Nd Floor";

    $input = preg_replace($ordinalregex, "strtolower('$1$2')", $input);

    print($input);

/e 修饰符告诉解释器使用 eval。现在这可行,但它不安全。如果您的输入由于 C 错误而具有 \0(空字符),则解释器将执行 \0 之后的字符串部分。

【讨论】:

  • /e 修饰符在 PHP 5.5 中已被弃用,可能是因为它不安全。 preg_replace_callback 现在是推荐的方法。
  • @lePunk - 即使在早期版本中,e 修饰符仍然被认为是不好的做法。 preg_replace_callback() 从 5.0 开始可用。
猜你喜欢
  • 1970-01-01
  • 2010-11-25
  • 2016-11-09
  • 1970-01-01
  • 1970-01-01
  • 2011-07-21
  • 2012-04-13
  • 2014-08-29
  • 2013-11-12
相关资源
最近更新 更多