如何在不编写正则表达式的情况下从字符串中解析日期?

How to parse dates from a string without writing a regular expression?

readr 包有一个名为 parse_number 的函数,它 returns string:

中的数字
readr::parse_number("Hello 2022!")

[1] 2022

是否有类似的方法从 string 返回日期? readr 有一个名为 parse_date 的函数,但它做了一些不同的事情:

readr::parse_date("X2018-01-11_poland")

Warning: 1 parsing failure.
row col   expected             actual
  1  -- date like  X2018-01-11_poland

[1] NA

期望的输出:

# the raw string is "X2018-01-11_poland"
2018-01-11

P.S。我对使用正则表达式执行此操作不感兴趣。

这是一个无正则表达式的想法,

parse_date(strsplit(x, '_', fixed = TRUE)[[1]][1], format = 'X%Y-%m-%d')
#[1] "2018-01-11"

不过,如果波兰部分也固定了,你可以再做,

parse_date(x, format = 'X%Y-%m-%d_poland')
#[1] "2018-01-11"

使用基数 R 或 stringrlubridate

的可能替代方案
as.Date(substr("X2018-01-11_poland", 2, 11), format = "%Y-%m-%d")
#> [1] "2018-01-11"

library(stringr)
library(lubridate)

ymd(str_sub("X2018-01-11_poland", 2, 11))
#> [1] "2018-01-11"

reprex package (v2.0.1)

于 2021-12-22 创建

lubridate 包中有 parse_date_time2 易于使用。

library(lubridate)
dstring <- "X2018-01-11_poland"
date <- parse_date_time2(dstring, orders='Ymd')
date
#[1] "2018-01-11 UTC"

1) 这仅使用基本 R,不使用任何正则表达式。它假设 (1) 日期之前只有字母和 spaces,就像问题中的情况一样,但如果需要,可以通过向 lets 添加额外的字符和 (2) 日期来轻松放宽是标准的日期格式。 chartr 将其第一个参数中的第 i 个字符转换为第二个参数中的第 i 个字符,用 space 替换每个字母。然后使用 as.Date。请注意,as.Date 会忽略末尾的垃圾信息,因此如果 lets 中没有的其他字符跟在日期后面也没关系。

x <- "X2018-01-11_poland"

lets <- paste(letters, collapse = "")
as.Date(chartr(lets, strrep(" ", nchar(lets)), tolower(x)))
## [1] "2018-01-11"

2) 如果我们知道字符串总是以 X 开头并且日期紧跟其后,那么我们可以只在 as.Date 格式字符串中指定前缀.它也不使用任何正则表达式,只使用基本 R.

as.Date(x, "X%Y-%m-%d")
## [1] "2018-01-11"

3) 如果您愿意妥协并使用非常简单的正则表达式——此处 \D 匹配任何非数字并且反斜杠必须在引号内加倍。 gsub 删除任何此类字符。

as.Date(gsub("\D", "", x), "%Y%m%d")
## [1] "2018-01-11"