R语言中如何提取模式间多段字符串并按需返回指定条目
在R中提取两段字符串间的多组匹配内容
问题场景
你需要从字符串里提取Fabricante:和CNPJ:之间的公司名称,目标字符串里有3组匹配结果,但用普通gsub要么只拿到第一条(非贪婪模式)要么只拿到最后一条(贪婪模式),尝试str_match_all也没成功,想要实现按需提取第1/2/3条,还能结合mutate批量处理数据集生成对应变量。
解决办法
1. 先提取所有匹配项,再按需取值
用stringr的str_extract_all可以一次性把所有符合条件的内容抓出来,之后直接按索引取对应条目:
library(stringr) # 模拟你的目标字符串 target_str <- "Fabricante: 阿尔法公司 CNPJ: 111 Fabricante: 贝塔工厂 CNPJ: 222 Fabricante: 伽马实业 CNPJ: 333" # 提取所有匹配的公司名 all_companies <- str_extract_all(target_str, "(?<=Fabricante: )(.*?)(?= CNPJ:)")[[1]] # 按需获取对应条目 all_companies[1] # 取第一条 all_companies[2] # 取第二条 all_companies[3] # 取第三条
这里用了正向断言:(?<=Fabricante: )确保匹配内容在Fabricante: 之后,(?= CNPJ:)确保匹配内容在 CNPJ:之前,精准定位区间,不会把前后的标识字符串带进来。
2. 结合dplyr::mutate批量处理数据集
如果要给整个数据集新增company_1、company_2、company_3这三个变量,可以这么写:
library(dplyr) library(purrr) library(stringr) df <- df %>% mutate( # 先把每行的所有匹配结果存成列表列 all_matches = str_extract_all(manufacturing_location, "(?<=Fabricante: )(.*?)(?= CNPJ:)"), # 按位置提取,没有对应匹配就填NA company_1 = map_chr(all_matches, ~ if (length(.x) >= 1) .x[1] else NA_character_), company_2 = map_chr(all_matches, ~ if (length(.x) >= 2) .x[2] else NA_character_), company_3 = map_chr(all_matches, ~ if (length(.x) >= 3) .x[3] else NA_character_) ) %>% # 可选:删掉临时的列表列 select(-all_matches)
3. 不用stringr的基础R实现
如果不想加载额外包,用基础R的gregexpr和regmatches也能实现:
# 提取所有匹配 matches <- regmatches(target_str, gregexpr("(?<=Fabricante: )(.*?)(?= CNPJ:)", target_str, perl = TRUE))[[1]] # 取对应条目 matches[1] matches[2] matches[3]
为什么之前的方法没成功?
- 普通
gsub不管贪婪还是非贪婪模式,都只会返回第一个或最后一个匹配结果,因为它的逻辑是替换整个字符串,只保留捕获组的内容 - 用
str_match_all时,需要注意它返回的是矩阵格式,要正确提取捕获组的列,比如str_match_all(target_str, "Fabricante: (.*?) CNPJ:")[[1]][,2]就能拿到所有匹配的公司名,之前可能是没取对列导致失败
内容的提问来源于stack exchange,提问作者Joao Francisco Pugliese
相关产品推荐
相关产品推荐

