当存在多个日期时间戳时,正则表达式提取第一个日期时间戳

3
给定一个包含多个日期时间戳的字符串,我想要提取第一个时间戳以及其之前的文本。
候选字符串可能有一个或多个时间戳。
后续的日期时间戳将用“sep =“ - ””分隔。
可能会有或没有在后续日期时间戳之间的文本,但一定会有一个sep。
日期时间格式:
每个单独的时间戳可能包含时间(即仅日期)。
如果时间戳包含时间,则格式将是_HHMM或_HHMMSS。
日期将始终是YYYYMMDD格式。
library(stringr)  

string   <- "TEXT_etc_20140530-20140825_1635-"
expected <- "TEXT_etc_20140530"

## using this pattern for the date_time stamp
##  8 digits, optional underscore with 4to6 digits, appearing exactly once, followed by "-"
. (\\d{8}(_\\d{4,6})?){1}-    # I am not concerned with potential of a 5-digit time stamp

## Attempts
pat1 <- "(TEXT)(.*?)(\\d{8}(_\\d{4,6})?){1}-";  str_extract(string, pat=pat1)
pat2 <-            "(\\d{8}(_\\d{4,6})?){1}-";  str_extract(string, pat=pat2)  ## date is correct
pat3 <-       "(.*?)(\\d{8}(_\\d{4,6})?){1}-";  str_extract(string, pat=pat3)
pat4 <-       "(.*?)(\\d{8}){1}-"            ;  str_extract(string, pat=pat4)

## Other potential string patterns
string   <- "TEXT_etc_20140530-diff_txet_20140825_1635-"
string   <- "TEXT_etc_20140530_123456-diff_txet_20140825_1635-"

你能帮我找出正则表达式中的错误吗?

R用户请注意:在R中,转义字符\本身也需要转义,因此上面的代码中使用了\\


第一个时间戳之前的所有值都是非数字吗? - MrFlick
感谢大家提供的多个答案。 - Ricardo Saporta
4个回答

5

将后面跟着任何内容的8位数字替换为这些8位数字本身:

# test data
string  <- c("TEXT_etc_20140530-20140825_1635-",
   "TEXT_etc_20140530-diff_txet_20140825_1635-",
   "TEXT_etc_20140530_123456-diff_txet_20140825_1635-")

sub("(\\d{8}).*", "\\1", string)
## [1] "TEXT_etc_20140530" "TEXT_etc_20140530" "TEXT_etc_20140530"

如果需要保留可选时间,则使用以下内容:
sub("(\\d{8}(.\\d{4,6})?)\\b.*", "\\1", string)
## [1] "TEXT_etc_20140530"        "TEXT_etc_20140530"      
## [3] "TEXT_etc_20140530_123456"

更新:添加了第二种解决方案并对其进行了更正。


1
它确实省略了时间,但也许我理解有误,这可能是原始问题所要求的。 - MrFlick
这个例子没有包含时间,但如果需要保留时间,则使用我刚添加的第二个 sub - G. Grothendieck

3
如何?
strings <- c("TEXT_etc_20140530-20140825_1635-",
    "TEXT_etc_20140530-diff_txet_20140825_1635-",
    "TEXT_etc_20140530_123456-diff_txet_20140825_1635-")

pat <- "^\\w*\\d{8}(_\\d{4,6})?"
str_extract(strings, pat=pat)

返回的是
[1] "TEXT_etc_20140530"      "TEXT_etc_20140530"     "TEXT_etc_20140530_123456"

2

这是一种方法:

pat <- '^(?U)(.*\\d{8}).*$'
gsub(pat, '\\1', string, perl=TRUE)
# [1] "TEXT_etc_20140530" "TEXT_etc_20140530" "TEXT_etc_20140530"
< p > (?U) 告诉解析器找到最短匹配。


1

你也可以尝试:

 library(stringi)
 stri_extract_first_regex(string, "[^0-9]+\\d{8}")
 #[1] "TEXT_etc_20140530" "TEXT_etc_20140530" "TEXT_etc_20140530"

或者

 str_extract(string, "[^0-9]+\\d{8}")
 #[1] "TEXT_etc_20140530" "TEXT_etc_20140530" "TEXT_etc_20140530"

提取时间:

要提取时间:

 stri_extract_first_regex(string, "[^0-9]+\\d{8}(?:_[0-9]{4,6})?")
 #[1] "TEXT_etc_20140530"        "TEXT_etc_20140530"       
 #[3] "TEXT_etc_20140530_123456"


 #data 
 string  <- c("TEXT_etc_20140530-20140825_1635-",
"TEXT_etc_20140530-diff_txet_20140825_1635-",
"TEXT_etc_20140530_123456-diff_txet_20140825_1635-")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接