You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用stringr::str_replace提取下划线分隔的第三个元素?

用str_replace提取下划线分隔字符串的第三个元素

嘿,我看你想用str_replace替代str_split来提取下划线分隔字符串里的第三个元素,不过你当前的正则因为贪婪匹配的问题没拿到正确结果,我来帮你修正下~

问题分析

你之前写的正则(.+)_(.+)_(.+)_*(.*)_*(.*)里,.+是贪婪匹配——它会尽可能多的吃掉字符,导致第一个.+直接吃到倒数第二个下划线的位置,最后捕获的\\3变成了字符串的最后一段(比如第一个例子里的feee),这就和你想要的结果背道而驰了。

修正方案

我们可以用明确匹配非下划线字符的方式来避免贪婪问题,正则写成:^[^_]+_[^_]+_([^_]+).*,然后用str_replace把整个字符串替换为捕获组\\1的内容,就能得到第三个元素了,同时也保留了分组。

测试代码及结果

library(tidyverse)
library(stringr)

# 构建测试数据
d <- enframe(
  c("asfe_01_AAAA_fses_feee", "asfe_87_BBBB_fses_feee", "99_fesf_CCCC_feee", "99_fesf_DDDD"),
  name = NULL, 
  value = "txt"
)

# 修正后的处理逻辑
d %>% 
  mutate(
    x = str_replace(txt, "^[^_]+_[^_]+_([^_]+).*", "\\1"),
    want_strsplit = str_split(txt, "_", simplify = TRUE)[, 3]
  )

运行后得到的结果和预期一致:

txtxwant_strsplit
asfe_01_AAAA_fses_feeeAAAAAAAA
asfe_87_BBBB_fses_feeeBBBBBBBB
99_fesf_CCCC_feeeCCCCCCCC
99_fesf_DDDDDDDDDDDD

正则解释

拆解一下这个正则的各个部分:

  • ^:锚定字符串开头,确保从最开始匹配,避免中间匹配的干扰
  • [^_]+:匹配任意不是下划线的字符(至少一个),刚好对应下划线分隔的单个元素
  • [^_]+_:匹配第一个元素加上后面的下划线分隔符
  • 重复一次[^_]+_,就完成了第二个元素和后续下划线的匹配
  • ([^_]+):这是我们的捕获组,专门匹配第三个元素(所有非下划线字符),后续用\\1调用这个组的内容
  • .*:匹配第三个元素之后的所有内容(不管有没有下划线,全部匹配掉)

这样str_replace就会把整个字符串替换成我们需要的第三个元素,和str_split的结果完全同步~

内容的提问来源于stack exchange,提问作者r.user.05apr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:03:31