替换字符串中的第n个数字

6

我有一组文件,它们的命名不正确。文件名如下。

Generation_Flux_0_Model_200.txt
Generation_Flux_101_Model_43.txt
Generation_Flux_11_Model_3.txt

我需要替换第二个数字(型号)并将现有数字加1。因此,正确的名称应该是

Generation_Flux_0_Model_201.txt
Generation_Flux_101_Model_44.txt
Generation_Flux_11_Model_4.txt

这是我写的代码。我想知道如何指定数字的位置(用新数字替换字符串中的第二个数字)?
reNameModelNumber <- function(modelName){

  #get the current model number
  modelNumber = as.numeric(unlist(str_extract_all(modelName, "\\d+"))[2])

  #increment it by 1
  newModelNumber = modelNumber + 1

  #building the new name with gsub 
  newModelName = gsub("  regex ", newModelNumber, modelName) 

  #rename
  file.rename(modelName, newModelName)


}


reactionModels = list.files(pattern = "^Generation_Flux_\\d+_Model_\\d+.txt$")

sapply(reactionFiles, function(x) reNameModelNumber(x))

你需要自增的数字是否总是在文件扩展名之前? - Wiktor Stribiżew
在文件扩展名之前加上“是”。 - SriniShine
1
使用 gsubfngsubfn("\\d+(?=\\.[^.]*$)", ~ as.numeric(x) + 1, reactionFiles, backref=0) - Wiktor Stribiżew
4个回答

8
我们可以使用 gsubfn 来增加 1。捕获数字 ((\\d+)),后跟字符串末尾的 . 和 'txt' ($`),然后将其替换为加 1 后的值。
library(gsubfn)
gsubfn("(\\d+)\\.txt$", ~ as.numeric(x) + 1, str1)
#[1] "Generation_Flux_0_Model_201"  "Generation_Flux_101_Model_44"
#[3] "Generation_Flux_11_Model_4"  

数据

str1 <- c("Generation_Flux_0_Model_200.txt", "Generation_Flux_101_Model_43.txt", 
                   "Generation_Flux_11_Model_3.txt")

6
回答这个问题,如果你想在一个字符串中递增某个数字,可以使用:
> library(gsubfn)
> nth = 2
> reactionFiles <- c("Generation_Flux_0_Model_200.txt", "Generation_Flux_101_Model_43.txt", "Generation_Flux_11_Model_3.txt")
> gsubfn(paste0("^((?:\\D*\\d+){", nth-1, "}\\D*)(\\d+)"), function(x,y,z) paste0(x, as.numeric(y) + 1), reactionFiles)
[1] "Generation_Flux_0_Model_201.txt"  "Generation_Flux_101_Model_44.txt" "Generation_Flux_11_Model_4.txt"  

nth在这里是要增加的数字块的序号。

模式细节

  • ^((?:\\D*\\d+){n}\\D*) - 捕获组1(可以通过gsubfn方法中的x访问其值):
    • (?:\\D*\\d+){n} - n个出现次数的
      • \\D* - 除了数字外的0个或多个字符
      • \\d+ - 1个或多个数字
    • \\D* - 0个或多个非数字
  • (\\d+) - 捕获组2(可以通过gsubfn方法中的y访问其值):一个或多个数字

1
感谢@wiktor提供的全面答案。有数字位置很有用,因为我有不同的命名转换,现在更新起来很容易了。 - SriniShine

4

使用基础R。

data <- c( # Just an example
  "Generation_Flux_0_Model_200.txt",
  "Generation_Flux_101_Model_43.txt",
  "Generation_Flux_11_Model_3.txt"
)

fixNameModel <- function(data){
  n <- length(data)

  # get the current model number and increment it by 1
  newn = as.integer(sub(".+_(\\d+)\\.txt", "\\1", data)) + 1L

  #building the new name with gsub
  newModelName <- vector(mode = "character", length = n)
  for (i in 1:n) {
    newModelName[i] <- gsub("\\d+\\.txt$", paste0(newn[i], ".txt"), data[i])
  }
  newModelName
}

fixNameModel(data)
[1] "Generation_Flux_0_Model_201.txt"  "Generation_Flux_101_Model_44.txt"
[3] "Generation_Flux_11_Model_4.txt"  

您现在可以执行类似于file.rename(modelName, fixNameModel(modelName))的操作。

编辑:

这里有一个更整洁的版本,但是它做出了更强的假设:

fixNameModel2 <- function(data) {
  sapply(
    strsplit(data, "_|\\."), 
    function(x) {
      x[5] <- as.integer(x[5]) + 1L
      x <- paste0(x, collapse = "_")
      gsub("_txt", ".txt", x, fixed = TRUE)
    } 
  )
}

2
假设数字总是出现在扩展名之前,正如评论中所提到的那样,这里有另一个基于R语言的解决方案,它更简单一些。
sapply(regmatches(tmp, regexec("\\d+(?=\\.)", tmp, perl=TRUE), invert=NA),
       function(x) paste0(c(x[1], as.integer(x[2]) + 1L, x[3]), collapse=""))

这将返回:
[1] "Generation_Flux_0_Model_201.txt"  "Generation_Flux_101_Model_44.txt"
[3] "Generation_Flux_11_Model_4.txt" 

regexec 使用 invert=NA,返回一个索引列表,其中每个列表元素都是匹配部分的索引,第二个索引元素返回匹配元素。 regmatches 获取此信息并返回一个字符向量列表,该列表沿着匹配项将原始字符串分解。将此列表馈送给 sapply,将第二个元素转换为整数并递增。然后粘贴结果以返回原子向量。

正则表达式 "\d+(?=\.)" 使用 perl 向前查找 "(?=\.)",查找不捕获点,但使用 "\d+" 捕获数字。

数据

tmp <- c("Generation_Flux_0_Model_200.txt", "Generation_Flux_101_Model_43.txt", 
"Generation_Flux_11_Model_3.txt")

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