正则表达式过滤,然后确定最新日期

时间:2016-10-25 18:34:35

标签: r regex

假设我有一个包含四个文件的目录:

someText.abcd.xyz.10Sep16.csv 
someText.xyz.10Sep16.csv
someText.abcd.xyz.23Oct16.csv 
someText.xyz.23Oct16.csv

这是名称的格式。我无法更改它们,除了日期会发生变化外,格式将保持不变。所有名称都以someText开头。接下来,有四个字母的代码(abcd)或后三个代码(xyz)。如果文件名具有四字母代码,则后面将始终包含三个字母的代码。最后有一个日期值。

我有两项任务。首先,我需要过滤出具有" abcd"的文件。零件。这将始终是一个四字符代码,显示在名称中的someText.之后。有没有办法纠正正则表达式去除这些值?

留下两个文件:

someText.xyz.10Sep16.csv
someText.xyz.23Oct16.csv

我只需要具有较晚日期的文件。有没有第二个正则表达式,我可以做提取日期,找到最新的,然后只保留该日期?我这样做是为了将文件设置为四:

myDir <- "\\\\myDir\\folder\\"
files <- list.files(path = myDir, pattern = "\\.csv$")

如果有人想要试用,那么这里是带有文件名的向量:

files <- c("someText.abcd.xyz.10Sep16.csv", "someText.xyz.10Sep16.csv", "someText.abcd.xyz.23Oct16.csv", "someText.xyz.23Oct16.csv")

3 个答案:

答案 0 :(得分:2)

这是我尝试简单的基础R回答

# regex subset 
files <- files[!grepl("^.*?\\.[[:alpha:]]{4}\\.", files)]

# get date
dates <- unlist(lapply(strsplit(files, "\\."), "[[", 3))

files[which.max(as.Date(dates, format = "%d%b%y"))]
# [1] "someText.xyz.23Oct16.csv"

答案 1 :(得分:1)

我认为这应该足够强大,可靠地运作。我使用dplyr传递结果并对其进行操作,并使用lubridate进行方便的日期提取(dmy)。几乎忘了:你需要加载magrittr来获取%$%管道。

我用“。”分割文件名,然后如果它们缺少四个字母的代码部分则滑过结果。将它们绑定到data.frame中以便于过滤等。在这里,过滤那些缺少四个字母的部分,然后选择具有最新日期的那个。

strsplit(files, "\\.") %>%
  setNames(files) %>%
  lapply(function(x){
    if(length(x) == 4){
      x[3:5] <- x[2:4]
      x[2] <- "noCode"
    }
    rbind(x) %>%
      as.data.frame()
  }) %>%
  bind_rows(.id = "fileName") %>%
  mutate(date = dmy(V4)) %>%
  filter(V2 == "noCode") %$%
  c(fileName[which.max(date)])

返回:“someText.xyz.23Oct16.csv”

答案 2 :(得分:1)

我确信这可以做得更紧凑,但这里有一个基本的答案:

# file names
file_names =c(
  "someText.abcd.xyz.10Sep16.csv",
  "someText.xyz.10Sep16.csv",
  "someText.abcd.xyz.23Oct16.csv",
  "someText.xyz.23Oct16.csv"
)

# the pattern to be tested
reg_file_names = regexec(
  pattern = "^someText\\.[a-z]{4}\\.[a-z]{3}\\.(.*).csv$",
  file_names
)

# parse out the matched dates, and look for the maximum
file_names[
  which.max(
    sapply(
      regmatches(
        x = file_names, m = reg_file_names
      ),
      function(match) {
        as.Date(
          ifelse(
            length(match) == 0,
            NA,
            match[2]
          ),
          format = "%d%b%y"
        )
      }
    )
  )
  ]

您需要的正则表达式相当简单,其余代码只是处理没有匹配的情况,并格式化日期以便可以比较它们。