用 M 上完成的单词替换 M 表示 N,但 M 是它自己


Replace M for N in words finished on M, but the M it self

问题:我需要在所有以"m"结尾的单词中将"m"替换为"n",而不是"m"本身。

示例文本:炸弹有一个 m。

预期回报:邦邦有一个m。

当前 PHP 代码:$txt = preg_replace('/(m)(?=''s|$)/i', 'n', $txt);

但它返回:Bombon有一个n。


奖励一:我希望"Word"[a-zA-ZÀ-ÿ],所以,3m不应该被替换为3n

奖励二(对于另一个类似的问题(:告诉我如何用Use Q for Iraq and Qatar替换Use Q for Irak and katar(替换所有出现的,除非单独出现(。

当您正在寻找仅出现在单词末尾的m时,即它后面应该跟着一个单词边界,但前面有一个字母。你可以像这样使用negative lookbehind

正则表达式/(?<=[A-Za-z])m'b/

解释

m'b匹配m后跟单词边界。所以Bombomm应该匹配。但我们只需要Bombom.所以使用negative lookbehind.

(?<=[A-Za-z])在匹配m之前寻找一个字母。

然后将其替换为n.

它与3m不匹配,因为m前面有一个数字。

正则表达式 101 演示

没有正则表达式,但这样可以做到。

function replaceLastLetter($search, $replace, $subject){
    $words = explode(" ", $subject);
    for($i=0; $i<count($words); $i++){
        $last = substr($words[$i], -1);
        if($last == $search && strlen($words[$i])>1){
            $words[$i] = substr($words[$i], 0, strlen($words[$i])-1).$replace;
        }
    }
    return implode(" ", $words);
}

https://3v4l.org/lJ4WN

您可以使用

[^'w]来匹配非字母/数字,并将它们再次包含在替换字符串中:

$input = "Bombom has an m, not 3m.";
$output = preg_replace("/([a-zÀ-ÿ])m($|[^'w])/i", "$1n$2", $input);
echo $output . "<br>";

输出:

炸弹有一个m,而不是3m。

正则表达式将获取前面的字母(必须是字母 ( a-zÀ-ÿ (,作为组 1,后面的非字母/数字[^'w](或字符串 $ 的末尾(作为组 2,并在替换字符串中分别使用 $1$2 恢复这些。

对于 Q 的情况,您可以使用以下内容:

$input = "Use Q for Iraq and Qatar";
$output = preg_replace("/(?:([a-zÀ-ÿ])q($|[^'w])|(^|[^'w])q($|[a-zÀ-ÿ]))/i",
                       "$1$3k$2$4", $input);
echo $output . "<br>";

输出:

使用 Q 表示伊拉克和卡塔尔

这里原理用OR运算(|(扩展。由于现在有 4 个捕获组,因此需要在替换字符串中还原所有四个捕获组,即使其中只有两个将实现。另外两个将是空字符串,因此如果它们也存在,它不会破坏结果。

正则表达式末尾的i选项可确保qQ匹配(不区分大小写(。