使用后向断言可选匹配符号的正则表达式问题
解决正则提取名称并移除冒号的问题
看起来你已经快摸到正确结果了,只是正则的匹配范围没控制好,才导致冒号被留在结果里。咱们来调整一下:
问题分析
你当前用的正则.*(?=:* my name)有两个小问题:一是.*是贪婪匹配任意字符,会把名称后面的冒号也纳入匹配范围;二是:*表示匹配0个或多个冒号,而你实际需要的是匹配0个或1个冒号,应该用:?。这两个点加起来,就导致Robert:被完整匹配出来了。
修正后的正则方案
我们需要明确:要提取的是**"my name"前面、不含冒号的名称部分**,同时兼容名称后带冒号或不带冒号的情况。直接把正则改成这样就能解决问题:
strings <- c("Robert: my name is Robert", "Michael my name is Michael", "Jack: I like turtles") regmatches(strings, regexpr("[^:]+(?=:? my name)", strings, perl = TRUE))
正则逻辑拆解
[^:]+:匹配任意非冒号的字符,直到遇到冒号或者"my name"前的空格,自动排除了名称后的冒号(?=:? my name):正向预查,确保后面跟着0个或1个冒号+空格+"my name",完美适配两种格式的目标字符串
运行这段代码后,就能得到你想要的结果:
[1] "Robert" "Michael"
另一种可选方案(捕获组方式)
如果你习惯用捕获组的思路,也可以这样写,不过需要用regexec来提取捕获组内容:
matches <- regexec("^([^:]+):? my name", strings) # 遍历提取每个匹配的捕获组 sapply(regmatches(strings, matches), function(x) if(length(x)>1) x[2] else NA)
这种方式需要处理结果索引,对于多元素向量要加遍历,所以第一种方案会更简洁直接。
内容的提问来源于stack exchange,提问作者Slug Pue
相关产品推荐
相关产品推荐

