2016-11-20 163 views
0

我在寻找帮助来解决我面临的preg_replace php函数的问题。 我做了一个正则表达式来匹配首字母缩略词,abreviation,...他们中的一些使用短划线或圆点来分隔字母,有些则没有。Preg_replace替换整个字符串而不是第一个捕获

\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

那么你是通过重新插入第一个捕获组“$ {1}”来替换整个匹配的字符串,然后添加一个'#'。你应该将你的信件捕获到一个组中,而不是点/斜线。你想通过重复{1,10}来完成什么? –

+0

为什么用'/ p {Lu}'(大写字母)和'/ i'修饰符(不区分大小写)?如果你只想使用大写字母,可以使用'\ p {Lu}'而不使用'/ i',或者如果你想混合使用'\ p {L}'而不使用'/ i'。 – Toto

+1

整个琴弦的预期结果是什么? – Toto

回答

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

技术上可以做到这一点没有回调,但正则表达式是丑陋的

相关问题