【问题标题】:PHP preg_replace: Case insensitive match with case sensitive replacementPHP preg_replace:不区分大小写的匹配与区分大小写的替换
【发布时间】:2013-10-19 11:53:42
【问题描述】:

我在 PHP 中使用 preg_replace 来查找和替换字符串中的特定单词,如下所示:

$subject = "Apple apple";
print preg_replace('/\bapple\b/i', 'pear', $subject);

结果为'pear pear'。

我希望能够以不区分大小写的方式匹配一个单词,但在替换它时尊重它的大小写 - 给出结果“Pear pear”。

以下工作,但对我来说似乎有点啰嗦:

$pattern = array('/Apple\b/', '/apple\b/');
$replacement = array('Pear', 'pear');
$subject = "Apple apple";
print preg_replace($pattern, $replacement, $subject);

有没有更好的方法来做到这一点?

更新:除了下面提出的一个很好的查询之外,就本任务而言,我只想尊重“标题大小写” - 所以无论单词的第一个字母是否是大写字母。

【问题讨论】:

  • 唯一不清楚的是:如果你的替换词和原词的长度不同,而原词在更高的位置有大写字母怎么办? IE。 'applE''pear' 然后呢?
  • 好点。出于此特定任务的目的,我只想尊重“标题大小写”(因此第一个字母是否为大写字母)。非常感谢您进一步澄清。

标签: php regex preg-replace


【解决方案1】:
$text = 'Grey, grey and grey';
$text = Find_and_replace_in_lowercase_and_uppercase('grey', 'gray', $text);
echo $text; //Returns 'Gray, gray and gray'

function Find_and_replace_in_lowercase_and_uppercase($find_term, $replace_term, $text)
{
        $text = Find_and_replace_in_lowercase($find_term, $replace_term, $text);
        $text = Find_and_replace_in_uppercase($find_term, $replace_term, $text);
        return $text;

}
function Find_and_replace_in_lowercase($find_term, $replace_term, $text)
{
        $find_term = lcfirst($find_term);
        $replace_term = lcfirst($replace_term);
        $text = preg_replace("/$find_term/",$replace_term,$text);
        return $text;
}
function Find_and_replace_in_uppercase($find_term, $replace_term, $text)
{
        $find_term = ucfirst($find_term);
        $replace_term = ucfirst($replace_term);
        $text = preg_replace("/$find_term/",$replace_term,$text);
        return $text;
}

【讨论】:

    【解决方案2】:

    这是我使用的解决方案:

    $result = preg_replace("/\b(foo)\b/i", "<strong>$1</strong>", $original);
    

    我会尽力解释为什么会这样:用() 包装你的搜索词意味着我想稍后访问这个值。由于它是 RegEx 中 pars 中的第一项,因此可以使用 $1 访问它,正如您在替换参数中看到的那样

    【讨论】:

    • 看看这与预期答案之间的区别。提醒所有工程师“保持简单”。
    • 此答案无法提供预期的结果/功能。
    • 如此简单!我怎么忘记了反向引用?谢谢!
    • 1 美元还是 0 美元?
    【解决方案3】:

    您可以使用 preg_replace_callback 来做到这一点,但这更加冗长:

    $replacer = function($matches) {
        return ctype_lower($matches[0][0]) ? 'pear' : 'Pear';
    };
    
    print preg_replace_callback('/\bapple\b/i', $replacer, $subject);
    

    此代码仅查看匹配的第一个字符的大小写以确定替换为什么;你可以修改代码来做一些更复杂的事情。

    【讨论】:

    • 我试过你的代码,但我得到了可捕获的致命错误:类闭包的对象无法转换为字符串...
    • @c3cris 我在上面的 sn-p 中错误地只写了preg_replace 而不是preg_replace_callback,尽管第一行中提到的内容是正确的。固定。
    • 这是一个更优雅的解决方案。一目了然,更短,更容易理解。 +1
    【解决方案4】:

    我想到了这种常见情况的实现:

    $data    = 'this is appLe and ApPle';
    $search  = 'apple';
    $replace = 'pear';
    
    $data = preg_replace_callback('/\b'.$search.'\b/i', function($matches) use ($replace)
    {
       $i=0;
       return join('', array_map(function($char) use ($matches, &$i)
       {
          return ctype_lower($matches[0][$i++])?strtolower($char):strtoupper($char);
       }, str_split($replace)));
    }, $data);
    
    //var_dump($data); //"this is peaR and PeAr"
    

    -当然,它更复杂,但适合任何职位的原始要求。如果您只寻找第一个字母,这可能是一个矫枉过正(请参阅@Jon's answer then)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-16
      • 2022-06-13
      • 1970-01-01
      相关资源
      最近更新 更多