在两个指定的子字符串之间提取子字符串

时间:2012-08-13 14:51:21

标签: regex r grep string-matching substr

我有一个带有以下模式的子串列表:

my.list <- list("file1\\subfile1-D.ext", "file12\\subfile9-D.ext", "file2\\subfile113-D.ext")

等等。我想将文件号和子文件号提取到包含文件/子文件号的数字数据框中。到目前为止,我一直在使用以下方法:

extract.file <- function(file.name){
  file.name <- sub("file", "", file.name)
  file.name <- sub("\\\\*subfile.*", "", file.name)
}

extract.subfile <- function(subfile.name){
  subfile.name <- sub("file.*subfile", "", subfile.name)
  subfile.name <- sub("-D.ext", "", subfile.name)
}

name.file <- lapply(my.list, extract.file)
name.file <- as.numeric(unlist(name.file))
name.subfile <- lapply(my.list, extract.subfile)
name.subfile <- as.numeric(unlist(name.subfile))

my.df <- data.frame(file=name.file, subfile=name.subfile)

我还首先使用来自substring.location库的stringr提取字符串位置(这会生成另一个包含起始值和结束值的列表),然后循环遍历这两个列表,但是这样太复杂了。有没有更好的方法来实现目标?

2 个答案:

答案 0 :(得分:5)

一些替代方案:
[编辑:strsplit可以获取一个数组并返回一个列表,与在rbind调用中嵌套一个apply相比,时间缩短了一半左右。]

my.df <- do.call( rbind, strsplit( unlist(my.list), split="(\\\\|-D.ext)" ) )
my.df <- data.frame( my.df )
names( my.df ) <- c("file", "subfile")

my.df <- do.call( rbind, strsplit( unlist(my.list), split="[^[:alnum:]]" ) )[, 1:2]
my.df <- data.frame( my.df )
names( my.df ) <- c("file", "subfile")

以这种方式做事的一件事是,如果所有输入都遵循原始的my.list样本,那么您将获得相当无价值且冗余的数据。

也许更好的解决方案可能是;

# Not sure why strsplit() returns an empty string on the first non-digit match,
# but it does and we account for it by dropping the first returned column.
my.list <- unlist( my.list )
my.df <- do.call( rbind, strsplit( my.list, split="[^[:digit:]]+" ) )[,-1]
my.df <- data.frame( my.list, my.df )
names( my.df ) <- c( "orig", "file", "subfile" )

我们已经节省了相当多的内存/存储而没有所有这些重复,我们获得了操作事物的能力,而不必担心文本/字符排序/表示。


检查?strsplit?regex?grep是否有匹配的内容。

data.frame设置非常简单... strsplit接受一个向量并返回一个列表,而do.call需要一个列表绑定在一起。

答案 1 :(得分:2)

这是一个带有反向引用的正则表达式,似乎可以满足您的要求:

sapply(my.list, function(x)gsub(".*\\\\(.*)-D\\.ext", "\\1", x))
[1] "subfile1"   "subfile9"   "subfile113"

"\\1"是一个反向引用,它返回括号内字符串的值。

相关问题