我搜索了堆栈溢出了一点,我发现的是,与Perl或Python相比,R中的正则表达式有点棘手且不方便。
我的问题如下。我的文件名很长,里面有信息。看起来如下:
20150416_QEP1_EXT_GR_1234_hs_IP_NON_060.raw
20150416_QEP1_EXT_GR_1234-1235_hs_IP_NON_060.raw
20150416_QEP1_EXT_GR_1236_hs_IP_NON_060_some_other_info.raw
20150416_QEP1_EXT_GR_1237_hs_IP_NON_060
我想从文件名中提取部分并将它们方便地转换为值,例如第一部分是日期,第二部分是机器缩写,下一部分是缩写,组缩写,样本编号等。 ..
我现在所做的是构建一个正则表达式,使(几乎)确定,我grep正确的字符串部分:
regex <- '([:digit:]{8})_([:alnum:]{1,4})_([:upper:]+)_ etc'
然后我使用sub
将每个剪切保存到变量中:
date <- sub(regex, '\\1', filename)
machine <- sub(regex, '\\2', filename)
etc
如果文件名具有正确的约定,则此方法有效。这总体上很难阅读,我正在寻找一种更方便的工作方式。我想过用_分割文件名并通过索引访问字符串可能是一个很好的解决方案。但有时,由于文件名通常是手工创建的,因此名称中缺少术语或其他信息,我正在寻找更好的解决方案。
有人能建议更好的方法吗?
修改
我想要创建的是一个对象,它具有提取和访问的文件名的所有信息......例如my_object$machine
左右......
答案 0 :(得分:1)
?regex
的帮助页面实际上提供的示例与Python的re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
完全相同(根据您的评论):
## named capture notables <- c(" Ben Franklin and Jefferson Davis", "\tMillard Fillmore") #name groups 'first' and 'last' name.rex <- "(?<first>[[:upper:]][[:lower:]]+) (?<last>[[:upper:]][[:lower:]]+)" (parsed <- regexpr(name.rex, notables, perl = TRUE)) gregexpr(name.rex, notables, perl = TRUE)[[2]] parse.one <- function(res, result) { m <- do.call(rbind, lapply(seq_along(res), function(i) { if(result[i] == -1) return("") st <- attr(result, "capture.start")[i, ] substring(res[i], st, st + attr(result, "capture.length")[i, ] - 1) })) colnames(m) <- attr(result, "capture.names") m } parse.one(notables, parsed)
从字符串中提取的正常方式(即R方式)如下:
text <- "Malcolm Reynolds"
x <- gregexpr("\\w+", text) #Don't forget to escape the backslash
regmatches(text, x)
[[1]]
[1] "Malcolm" "Reynolds"
您可以使用参数perl=TRUE
:
regexpr("(?P<first_name>\\w+) (?P<last_name>\\w+)", text, perl=TRUE)
但是regmatches
不支持它,因此需要创建自己的函数来处理它,这在帮助页面中给出:
parse.one <- function(res, result) {
m <- do.call(rbind, lapply(seq_along(res), function(i) {
if(result[i] == -1) return("")
st <- attr(result, "capture.start")[i, ]
substring(res[i], st, st + attr(result, "capture.length")[i, ] - 1)
}))
colnames(m) <- attr(result, "capture.names")
m
}
应用于您的示例:
text <- "Malcolm Reynolds"
x <- regexpr("(?P<first_name>\\w+) (?P<last_name>\\w+)", text, perl=TRUE)
parse.one(text, x)
first_name last_name
[1,] "Malcolm" "Reynolds"
回到最初的问题:
filenames <- c("20150416_QEP1_EXT_GR_1234_hs_IP_NON_060.raw", "20150416_QEP1_EXT_GR_1234-1235_hs_IP_NON_060.raw", "20150416_QEP1_EXT_GR_1236_hs_IP_NON_060_some_other_info.raw", "20150416_QEP1_EXT_GR_1237_hs_IP_NON_060")
regex <- '(?P<date>[[:digit:]]{8})_(?P<machine>[[:alnum:]]{1,4})_(?P<whatev>[[:upper:]]+)'
x <- regexpr(regex,filenames,perl=TRUE)
parse.one(filenames,x)
date machine whatev
[1,] "20150416" "QEP1" "EXT"
[2,] "20150416" "QEP1" "EXT"
[3,] "20150416" "QEP1" "EXT"
[4,] "20150416" "QEP1" "EXT"