如何让preg_replace仅替换捕获组1而非组0以生成正确的Twitter提及链接
解决方案
你遇到的问题根源是正则中的(?:^|[^>])作为非捕获前缀,会被包含在完整匹配结果(分组0)中,直接替换会把前缀(比如你示例里的空格)一起覆盖,导致多余内容被修改。可以通过两种方式解决:
方案1:使用零宽正向回顾断言(推荐)
把前缀匹配规则放到正向回顾断言中,断言内容不会被纳入完整匹配结果,这样分组0就和你需要替换的分组1内容完全一致:
preg_replace( '/(?<=^|[^>])(@' . $data->entities->user_mentions[$i]->screen_name . ')/', '<a href="https://twitter.com/' . $data->entities->user_mentions[$i]->screen_name . '">@' . $data->entities->user_mentions[$i]->screen_name . '</a>', $data->text );
注:该写法要求PHP版本≥7.3,支持可变宽度的正向回顾断言。
方案2:捕获前缀后在替换时保留
如果你的PHP版本较低不支持可变宽度回顾,可以把前缀改为捕获分组,替换时把前缀原样拼接回去,避免空格被覆盖:
preg_replace( '/((?:^|[^>]))(@' . $data->entities->user_mentions[$i]->screen_name . ')/', '$1<a href="https://twitter.com/' . $data->entities->user_mentions[$i]->screen_name . '">@' . $data->entities->user_mentions[$i]->screen_name . '</a>', $data->text );
其中$1对应你匹配到的前缀(行首标识或者空格等非>字符),替换时会原样保留,不会出现丢失空格的问题。
内容的提问来源于stack exchange,提问作者lolc
相关产品推荐
相关产品推荐

