【问题标题】:Preg_replace replace the whole string instead of the first capturingpreg_replace 替换整个字符串而不是第一次捕获
【发布时间】:2016-11-20 11:02:46
【问题描述】:

我正在寻求帮助来解决我在使用 preg_replace php 函数时遇到的问题。 我做了一个正则表达式来匹配首字母缩写词,缩写,......其中一些使用破折号或点来分隔字母,有些则没有。

\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,10} 重复来完成什么?
  • 为什么使用\p{Lu}(大写字母)和/i修饰符(不区分大小写)?如果您只需要大写,请使用\p{Lu} 而不使用/i,或者如果您想混合使用大小写,请使用\p{L} 而不使用/i
  • 整个字符串的预期结果是什么?
  • 大家好。谢谢你的意见。 Sebastian,我只想将首字母缩写词限制为 10 个字母。托托,你说得对,没用,我只是忘了删除/i。专家的结果是把 C.G. P-U.T.O.K.L.我进入 CGPUTOKL。

标签: php regex preg-replace pcre


【解决方案1】:

您需要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解释。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-13
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多