当多个存在时,正则表达式提取第一个date_time标记

时间:2014-08-27 19:33:14

标签: regex r

给定一个包含多个date_time标记的字符串,我想提取第一个标记及其前面的文字

  • 候选字符串可以有一个或多个时间戳
  • 后续的date_time标记将由sep="-"
  • 分隔
  • 后续的date_time邮票之间可能会有或可能没有文字,但肯定会有一个sep

date_time格式:

  • 每个邮票可能包含也可能不包含时间(即日期)
  • 如果邮票有时间,则格式为_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要求转义转义字符\本身,因此上面代码中的\\

4 个答案:

答案 0 :(得分: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 :(得分: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 :(得分:2)

这是一种方式:

pat <- '^(?U)(.*\\d{8}).*$'
gsub(pat, '\\1', string, perl=TRUE)
# [1] "TEXT_etc_20140530" "TEXT_etc_20140530" "TEXT_etc_20140530"

(?U)告诉解析器找到最短的匹配。

答案 3 :(得分: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-")