使用正则表达式从R中的字符串中提取日期

时间:2017-08-22 19:32:50

标签: r regex

我有以下数据框:

    V1 <- c("path/to/file/filename-Aug-4-2017-_to-Aug-4-2017_otherinfo_.csv", "otherpath/to/file/filename-Aug-18-2017-_to-Aug-18-2017_otherinfo_.csv")
    df <- as.data.frame(V1)

我希望能够将日期(格式化为日期)提取到名为df $ Date的新列中。在使用正则表达式和str_extract的组合之前,我已经完成了类似的事情:

    df$Date <- str_extract(df$V1, "\\d{4}-\\d{2}-\\d{2}")

但是我不确定如何使用这种格式的日期来实现这一点,并且真的不能理解正则表达式。任何帮助将不胜感激。

也对其他方法或方法持开放态度。谢谢!

2 个答案:

答案 0 :(得分:4)

如果你有一个非常好的输入格式并且你知道日期符合three_letters-one_or_two_digits-four_digits模式,你可以使用

df$Date <- sub(".*?\\b([A-Za-z]{3}-\\d{1,2}-\\d{4})\\b.*", "\\1", df$V1)

查看R online demo

V1 <- c("path/to/file/filename-Aug-4-2017-_to-Aug-4-2017_otherinfo_.csv", "otherpath/to/file/filename-Aug-18-2017-_to-Aug-18-2017_otherinfo_.csv")
df <- as.data.frame(V1)
df$Date <- sub(".*?\\b([A-Za-z]{3}-\\d{1,2}-\\d{4})\\b.*", "\\1", df$V1)

<强>详情

  • .*? - 任意0个字符,尽可能少,直到第一次出现......
  • \\b - 字边界
  • ([A-Za-z]{3}-\\d{1,2}-\\d{4}) - 第1组(后来从替换模式引用\1反向引用):
    • [A-Za-z]{3} - 3个ASCII字母
    • - - 连字符
    • \\d{1,2} - 1或2位数字
    • - - 连字符
    • \\d{4} - 4位数
  • \\b - 字边界
  • .* - 字符串末尾的任何0+字符。

因此,将其替换为\1仅保留使用(...)模式部分捕获的文本。

如果你需要更高的精度(如果你的输入比可能的更麻烦),你可以尝试一个详细的正则表达式,如

df$Date <- str_extract(df$V1, "(?i)\\b(Jan|Feb|Ma[ry]|Apr|Ju[nl]|Aug|Sept?|Oct|Nov|Dec)-\\d{1,2}-\\d{4}\\b")

请参阅regex demo

<强>详情:

  • (?i) - 不区分大小写的修饰符(内联选项)
  • \b - 字边界
  • (Jan|Feb|Ma[ry]|Apr|Ju[nl]|Aug|Sept?|Oct|Nov|Dec) - 替代方案之一:JanFebMarMay,4月, Jun or七月, {八月{1}} {九月{1}} {九月{1}} {十月{1}} 11月, Dec`
  • or - 连字符
  • , - 一位或两位数字
  • , - 连字符
  • or - 四位数字
  • - - 一个单词边界。

答案 1 :(得分:1)

基础R替代解决方案:

sub(".+(.{3}-[0-9]{1,2}-[0-9]{4}).+", "\\1", df$V1)

"Aug-4-2017"  "Aug-18-2017"

说明:

  • 首先查找四位数字:[0-9]{4}
  • 前面必须有一个连字符和一位或两位数字:-[0-9]{1,2}-,前面还有一个连字符。
  • 最后,在所有这些之前的任何三个字符:.{3}并保留第一个匹配(括号中的所有内容),而不是其他任何内容。

修改

根据Wiktor的评论略有改进:

sub(".{0,}(.{3}-[0-9]{1,2}-[0-9]{4}).{0,}", "\\1", df$V1)