正则表达式提取前n个数字和所有字母

时间:2019-03-11 22:58:11

标签: r regex

我有这个字符向量

[1] "0204Aug"    "30Aug01Sep"    "0608Sep"   "2022Sep"    "2729Sep"    "1113Oct"    "2527Oct"    "0103Nov"    "1517Nov"    "29Nov01Dec"

并且我想为每个元素提取开始日期和结束日期(在2个单独的向量或data.frame中,如果已经采用Date格式则更好)。

我能够获得结束日期,但是我想使用正则表达式和stringr中的str_extract来完成

str_sub(dates_raw, 3, 8)

对于开始日期,我得到了此正则表达式以使其与前两位数字相匹配

\d{2}(?=\d{2})

和匹配字母

[A-z]{3}
[A-z]{3}$

但是当我尝试将它们合并到单个正则表达式中时,我一无所获

\d{2}(?=\d{2})[A-z]
> Your regular expression does not match the subject string.

所需的输出

[1] "02 Aug"    "30 Aug"    "06 Sep"
[1] "04 Aug"    "01 Sep"    "08 Sep" 

2 个答案:

答案 0 :(得分:1)

这里是使用str_replace

的选项
library(tidyverse)
ss %>%
    str_replace("([\\d+]{2})([\\d+]{2})([A-Za-z]{3})", "\\1\\3\\2\\3") %>%
    str_split("(?<=[A-Za-z])(?=\\d)") %>%
    map(~setNames(as.Date(.x, format = "%d%b"), c("start", "end")))
#[[1]]
#       start          end
#"2019-08-02" "2019-08-04"
#
#[[2]]
#       start          end
#"2019-08-30" "2019-09-01"
#
#[[3]]
#       start          end
#"2019-09-06" "2019-09-08"
#
#[[4]]
#       start          end
#"2019-09-20" "2019-09-22"
#
#[[5]]
#       start          end
#"2019-09-27" "2019-09-29"
#
#[[6]]
#       start          end
#"2019-10-11" "2019-10-13"
#
#[[7]]
#       start          end
#"2019-10-25" "2019-10-27"
#
#[[8]]
#       start          end
#"2019-11-01" "2019-11-03"
#
#[[9]]
#       start          end
#"2019-11-15" "2019-11-17"
#
#[[10]]
#       start          end
#"2019-11-29" "2019-12-01"

这将返回list个对象中的一个Date个对象。如果您更喜欢listcharacter字符串,请删除as.Date行。


样本数据

ss <- c("0204Aug",    "30Aug01Sep",    "0608Sep",   "2022Sep",    "2729Sep",    "1113Oct",    "2527Oct",    "0103Nov",    "1517Nov",    "29Nov01Dec")

答案 1 :(得分:1)

我认为,仅对于正则表达式而言,这里的逻辑太复杂了,因为它将需要在某些(但不是全部)实例中重用Month值。幸运的是,我们可以做的比R多得多。

在这里,我们遍历日期向量,并使用正则表达式提取所有日期值和所有​​月份值。然后,我们可以将它们粘贴回去以获得正确的日期值。

dates <- c("0204Aug", "30Aug01Sep", "0608Sep", "2022Sep", "2729Sep", "1113Oct", "2527Oct", "0103Nov", "1517Nov", "29Nov01Dec")

library(stringr)
lapply(dates, function(date) {
    days = str_match(date, '([0-9]{2}).*([0-9]{2})')[,-1]
    month = str_match(date, '([A-z]{3})[0-9]*([A-z]{3})?')[,-1]
    month = na.omit(month)
    dates = paste(days, month)
})

[[1]]
[1] "02 Aug" "04 Aug"

[[2]]
[1] "30 Aug" "01 Sep"

[[3]]
[1] "06 Sep" "08 Sep"

[[4]]
[1] "20 Sep" "22 Sep"

[[5]]
[1] "27 Sep" "29 Sep"

[[6]]
[1] "11 Oct" "13 Oct"

[[7]]
[1] "25 Oct" "27 Oct"

[[8]]
[1] "01 Nov" "03 Nov"

[[9]]
[1] "15 Nov" "17 Nov"

[[10]]
[1] "29 Nov" "01 Dec"

stringr::str_match使我们可以为多个捕获组提供括号,从而使我们从每个项目中提取2套双精度数或2套月份样式字符串。它返回一个数据帧,第一列中有匹配项(由于只需要捕获组,所以将其删除),下一个2组中有2个捕获组。

对于“月”值,我们将第二个捕获组设为?可选,如果找不到,它将返回NA。我们用NA放下na.omit,然后利用paste的属性,即在给定2个长度不相等的向量时,如果只找到一个,则重复较短的向量来重复月份。