如何在不编写正则表达式的情况下从字符串中解析日期?
Posted
技术标签:
【中文标题】如何在不编写正则表达式的情况下从字符串中解析日期?【英文标题】:How to parse dates from a string without writing a regular expression? 【发布时间】:2022-01-23 18:16:40 【问题描述】:readr
包有一个名为 parse_number
的函数,它返回 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
附:我对使用正则表达式不感兴趣。
【问题讨论】:
只需指定format
,根据strptime()
约定:readr::parse_date("X2018-01-11_poland", format = "X%Y-%m-%d_poland")
。
您对为此使用正则表达式的反感究竟是什么?精心设计的正则表达式可以对大多数正则表达式问题具有鲁棒性,并在性能和弹性方面提供相当不错的类日期提取结果。
【参考方案1】:
这是一个无正则表达式的想法,
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"
【讨论】:
在添加fixed=TRUE
之前,它并不是完全无正则表达式的,即使它是单字符正则表达式 :-)
哈哈哈,是的@r2evans。我们需要完全绕过正则表达式引擎;P
parse_number() 本身也使用正则表达式,但您没有“看到”它。这个问题有点像“没有车我怎么能开车”。【参考方案2】:
使用基础 R 或 stringr
和 lubridate
的可能替代方案
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 日创建
【讨论】:
【参考方案3】:lubridate
包有parse_date_time2
,易于使用。
library(lubridate)
dstring <- "X2018-01-11_poland"
date <- parse_date_time2(dstring, orders='Ymd')
date
#[1] "2018-01-11 UTC"
【讨论】:
【参考方案4】:1) 这仅使用基本 R 并且不使用任何正则表达式。它假设 (1) 日期之前只有字母和空格,就像问题中的情况一样,但如有必要,可以通过在 let 中添加其他字符来轻松放宽;(2) 日期采用标准日期格式. chartr 将第一个参数中的第 i 个字符转换为第二个参数中的第 i 个字符,用空格替换每个字母。然后使用 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 开头并且 Date 紧随其后,那么我们可以在 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"
【讨论】:
以上是关于如何在不编写正则表达式的情况下从字符串中解析日期?的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用 CURDATE、MONTH、YEAR 等 DATE 函数的情况下从 RDBMS 获取当前月份记录
如何在不与 MainActivity 交互的情况下从通知中打开片段页面?
如何在不使用子进程的情况下从 python 自动化脚本中运行 python 'sdist' 命令?
如何编写一个正则表达式命令在 python 中将字符串转换为日期时间格式?