Preg_replace替换整个字符串而不是第一次捕获

时间:2016-11-20 11:02:46

标签: php regex preg-replace pcre

我正在帮助解决我在preg_replace php函数中遇到的问题。 我制作了一个正则表达式来匹配首字母缩略词,abreviation,...其中一些使用短划线或点来分隔字母,有些则不是。

\p{Lu}+(\p{Zs}?[.-]\p{Zs}?){1,10}

我的目的是用#替换短划线和点,我试图使用:

$re = '/\p{Lu}+(\p{Zs}?[.-]\p{Zs}?){1,10}/i';
$str ='normal text C.G. P- U.T.O .K.L. another normal text';
$subst = '${1}#';
$result = preg_replace($re, $subst, $str);

根据我的理解,这应该替换第一个捕获组(破折号或点)并用#替换它。但事实上,它取代了这封信。

例如,在此字符串 C.G中。 P-U.T.O .K.L。我希望 CGPUTOKL ,但实际上我有。#。 # - #。#。#。#。#..

您可以访问以下所有内容:https://regex101.com/r/gkeGiw/4

你能告诉我哪里错了(以及为什么)?

提前谢谢你,

问候,

查尔斯

1 个答案:

答案 0 :(得分:0)

您需要preg_replace_callback。正如@SebastianProske所说,你抓住了你不想要的东西。但是,您不能在重复模式中捕获您想要的位,因为最后一个匹配会覆盖所有先前的匹配,因此您只能获得每个匹配的最后一个字母。您应匹配整个首字母缩略词,然后擦除匹配。假设每个缩写最少2个字母:

$text_abbreviation_normalised = preg_replace_callback(
    '/\p{Lu}(?:(?:\p{Zs}*[.-]\p{Zs}*)?\p{Lu}){1,9}(?:\p{Zs}*\.)?/',
    function($matches) {
        return preg_replace('/\P{Lu}+/', '', $matches[0]);
    },
    $text
);

https://regex101.com/r/gkeGiw/7的解释。

技术上可以在没有回调的情况下做到这一点,但正则表达式将是 hideous

相关问题