【问题标题】:Parsing date in Mon, DD, YYYY format using RegEx in R使用 R 中的 RegEx 以 Mon、DD、YYYY 格式解析日期
【发布时间】:2015-08-05 15:47:30
【问题描述】:

我正在尝试从一串文本中解析日期。我假设最好的方法是正则表达式,但我还没有找到有效的解决方案。

首先,我使用 CSS 选择器从网站中获取日期。

date <-html_nodes(x=doc, css=".middleheadline+ .topnewsbar b") %>% html_text()

这会产生:

[1] "\r\n        Washington,\r\n        Jan 5, 2011"

我想从此字符串中提取日期本身(此处为 2011 年 1 月 5 日)。注意:月份可以是任何月份,日期可以是任何日期,年份可以是 2011-2015 之间的任何时间,所以我试图找到一个通常可以解析 Mon D[D] 中的日期的表达式, YYYY 格式。

这是一次尝试:

date <-str_extract_all(string=date, pattern='[A-Z][a-z]{3,4} ([0-9]{1,2}), [0-9]{4}')

这会产生character(0)

还有一个:

grep("[A-Z][a-z]{3,4} ([0-9]{1,2}), [0-9]{4}", date, value=TRUE)

这也会产生character(0)

有什么建议吗?

【问题讨论】:

  • 也许grep("\\w{3,4} \\d{1,2}, \\d{4}, date, value=TRUE) 我还没有测试过这个。 \\w 标签将匹配字母字符,\\d 标签匹配数字。
  • 日期总是在字符串的末尾,还是总是在最后一个"\r\n"之后?
  • 我同意 Joshua 的暗示,即我们需要更多关于输入内容的信息——而不仅仅是日期的内容。只要我们能识别输入,转换为实际日期类型就足够容易了。如果它总是在输入字符串的末尾,那它真的很容易
  • 谢谢! grep 解决方案仍然生成整个字符串,但 strsplit 代码有效。对于我正在抓取的许多网站,日期在"\r\n" 之后,但不是全部。

标签: r regex date


【解决方案1】:

您也可以试试strsplit()。有时我更喜欢它而不是令人麻木的正则表达式。

test <- c("\r\n        Washington,\r\n        Jan 5, 2011",
    "\r\n        Boston,\r\n        Mar 15, 2015")

vapply(strsplit(test, ".*\n\\s+"), "[", "", 2)
# [1] "Jan 5, 2011"  "Mar 15, 2015"

as.Date(vapply(strsplit(test, ".*\n\\s+"), "[", "", 2), "%b %d, %Y")
# [1] "2011-01-05" "2015-03-15"

【讨论】:

    【解决方案2】:

    你可以试试这个:

    date <-str_extract_all(string=date, pattern='\\w+\\s\\d+(st)?(nd)?(rd)?(th)?,\\s+\\d+')
    

    HERE测试链接。

    【讨论】:

    • 谢谢!我必须添加双斜杠才能使其工作:date &lt;-str_extract_all(string=date, pattern='\\w+\\s\\d+(st)?(nd)?(rd)?(th)?,\\s+\\d+')
    【解决方案3】:

    转换日期的函数:

    make_dates <- function(x, date_format=TRUE, split="\n") {
      dates <- lapply(strsplit(x, split), function(x) {
        grep("\\w+ \\d+, \\d+", x, value=T)})
    
      if(date_format) {
        strptime(gsub("\\s", "", dates), format="%b%d,%Y")
      } else { gsub(".*?(\\w.*)", "\\1", dates)}
    }
    
    test <- c("\r\n        Washington,\r\n        Jan 5, 2011",
           "\r\n        Boston,\r\n        Mar 15, 2015")
    
    make_dates(test)
    #[1] "2011-01-05 EST" "2015-03-15 EDT"
    make_dates(test, FALSE)
    #[1] "Jan 5, 2011"  "Mar 15, 2015"
    

    【讨论】:

      【解决方案4】:

      这是一个正则表达式,它将以各种 MDY 格式返回字符串中的日期,并带有各种分隔符。请务必在您的过程中设置case insensitve 选项。

      它会进行一些基本的错误检查,但会允许两位数的年份;并且还允许一个日期,例如 2015 年 2 月 31 日

      \b((?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*|(?:0?[1-9]|1[0-2]))(?:\s*([- /.])\s*)(?:(0?[1-9]|[12]\d|3[01])(?:st|nd|rd|th)?),?\2((?:19|2\d)?\d{2})\b
      

      【讨论】:

        【解决方案5】:

        我认为这就足够了:

        [A-Z][a-z]{2} \d{1,2}, 201[1-4]
        

        演示:https://regex101.com/r/eW3jV6/1

        哪个月份的缩写是 5 或 4 个字符长?您的正则表达式失败,因为您有 [A-Z][a-z]{3,4} 表示一个大写字母字符后跟三个或四个小写字母字符。我不熟悉有 5 个字符缩写的月份。

        您的字符串 Jan 有 3 个字符长,但其中只有 2 个字符是小写的。

        当前正则表达式的演示:https://regex101.com/r/bJ6gT3/1

        如果月份和日期和/或年份之间可能存在多个空格,请添加\h+;或者如果没有空格,请使用\h*

        【讨论】:

        • 有些日期使用 3 个字符的缩写,而另一些则是完整的月份名称(4 到 9 个字符之间)。我正在尝试找到可以处理月份名称的所有排列的东西。
        • 您可以使用(Jan(uary)?|Feb(urary)?|Mar(ch)?) 等分组。然后检查日期和年份。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-02-13
        • 1970-01-01
        • 2019-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多