在R语言中提取mm/dd/yyyy与m/dd/yyyy格式日期的问题
这个问题的核心是正则表达式里的贪婪匹配在搞鬼!让我给你拆解原因,再给出几个靠谱的解决方案:
首先,你当前用的gsub(".*(\\d{1,2}/\\d{1,2}/\\d{4}).*", "\\1", string)里,.*是贪婪匹配模式——它会尽可能多地消耗字符串内容,直到后面的正则能匹配为止。在你的示例字符串里,.*会一路匹配到"20 French From home 1",剩下的"2/27/2019"刚好符合\d{1,2}/\d{1,2}/\d{4}的模式,所以捕获到的就是被截断后的日期,这就是为什么结果不对。
方案1:改用非贪婪匹配
把贪婪的.*改成非贪婪的.*?,这样它会尽可能少地匹配内容,优先让后面的日期正则捕获完整的日期:
string <- "20 French From home 12/27/2019" gsub(".*?(\\d{1,2}/\\d{1,2}/\\d{4}).*", "\\1", string)
运行后就能得到预期的12/27/2019。
方案2:用负向断言精确限定匹配(需Perl模式)
如果你想更严谨,避免日期前面的数字干扰,可以用负向零宽断言(?<!\\d),确保日期的第一个数字前面不是数字字符:
gsub(".*(?<!\\d)(\\d{1,2}/\\d{1,2}/\\d{4}).*", "\\1", string, perl = TRUE)
这里必须加上perl = TRUE,因为R的基础正则引擎不支持零宽断言,启用Perl模式后才能使用这个语法。
方案3:用更简洁的字符串提取函数(推荐)
如果你的需求只是提取字符串中的日期,没必要用gsub做替换,直接用stringr包的str_extract函数更直观,它会直接返回第一个匹配的目标子串:
library(stringr) str_extract(string, "\\d{1,2}/\\d{1,2}/\\d{4}")
这个方法代码更简洁,可读性也更高,适合日常的字符串提取场景。
内容的提问来源于stack exchange,提问作者Julianne Kubes
相关产品推荐
相关产品推荐

