从下划线分隔字符串提取指定元素:gsub正则匹配异常问题
问题分析与解决
为什么正则对aa无效?
你的正则用了.*这种贪婪匹配模式,它会尽可能多地吞噬字符,这就是问题根源:
aa按下划线分割后共有13个部分,你的正则要求捕获组后要有3个_.*(即3个下划线分割的后续内容),但aa只有2个后续部分(galaxycombos、20220520)。贪婪模式下,前面的.*_会多吞一组内容,把primaria_也包含进去,导致捕获组拿到的是primaria而非目标myproducta。- 而
cc按下划线分割后有14个部分,捕获组后正好有3个后续部分,贪婪匹配刚好停在目标前,所以能正确拿到myproductb。
正确的解决方法
方法1:改用非贪婪匹配
把正则里的.*换成.*?(非贪婪模式),让每个匹配段只到下一个下划线就停止:
# 处理aa gsub(aa, pattern = ".*?_.*?_.*?_.*?_.*?_.*?_.*?_.*?_.*?_(.*?)_.*?_.*?_.*?", replacement = "\\1", perl = TRUE) # 处理cc gsub(cc, pattern = ".*?_.*?_.*?_.*?_.*?_.*?_.*?_.*?_.*?_(.*?)_.*?_.*?_.*?", replacement = "\\1", perl = TRUE)
方法2:分割字符串后提取(更直观)
用strsplit把字符串按下划线分割成数组,直接提取第11个元素(目标在两个字符串里都是第11位):
# 提取aa的目标 strsplit(aa, "_")[[1]][11] # 提取cc的目标 strsplit(cc, "_")[[1]][11]
方法3:精准正则匹配
用非捕获组匹配前10个下划线分割段,直接捕获第11段内容:
# 处理aa gsub(aa, pattern = "^(?:[^_]+_){10}([^_]+).*", replacement = "\\1", perl = TRUE) # 处理cc gsub(cc, pattern = "^(?:[^_]+_){10}([^_]+).*", replacement = "\\1", perl = TRUE)
内容的提问来源于stack exchange,提问作者Omar Gonzales
相关产品推荐
相关产品推荐

