正则表达式,返回特定字母后面的数字,直到下一个字母

时间:2017-03-08 15:45:22

标签: r regex string substring

我需要一个正则表达式,它返回一个特定的字母和下面的(一个或两个)数字,直到下一个字母。 例如,我想在R

中使用正则表达式提取公式中有多少个碳(C)
strings <- c("C16H4ClNO2", "CH8O", "F2Ni")

我需要一个表达式,它返回C的数字,该数字可以是一个或两个数字,并且不会返回氯(Cl)之后的数字。

substr(strings,regexpr("C[0-9]+",strings) + 1, regexpr("[ABDEFGHIJKLMNOPQRSTUVWXYZ]+",strings) -1)
[1] "16" "C"  ""  

但我想要回复的答案是

"16","1","0"

此外,我希望正则表达式自动定位下一个字母并在它之前停止,而不是将我指定的最终位置指定为不是C的字母。

4 个答案:

答案 0 :(得分:9)

CHNOSZ包中的

makeup将解析化学式。以下是一些使用它的替代方案:

1)创建此类完全解析公式的列表L,然后检查每个公式是否有"C"组件并返回其值,如果没有则返回0:

library(CHNOSZ)

L <- Map(makeup, strings)
sapply(L, function(x) if ("C" %in% names(x)) x[["C"]] else 0)
## C16H4ClNO2       CH8O       F2Ni 
##         16          1          0 

请注意,如果您有其他要求,L是完全解析的公式列表:

> L
$C16H4ClNO2
 C  H Cl  N  O 
16  4  1  1  2 

$CH8O
C H O 
1 8 1 

$F2Ni
 F Ni 
 2  1 

1a)通过向每个列表组件添加c(C = 0),我们可以避免测试碳的存在,从而产生以下sapply行的较短版本):

sapply(lapply(L, c, c(C = 0)), "[[", "C")

2)除了名称之外,(1)的这一行变体给出了与(1)中相同的答案。它为每个公式附加"C0"以避免必须测试碳的存在:

sapply(lapply(paste0(strings, "C0"), makeup), "[[", "C")
## [1] 16  1  0

2a)以下是(2)的变体,通过使用lapply接受矩阵的事实来消除makeup

sapply(makeup(as.matrix(paste0(strings, "C0"))), "[[", "C")
## [1] 16  1  0

答案 1 :(得分:1)

如果我理解你的问题,你就会找两件事:

  • C +紧随其后的数字=&gt; 匹配此号码
  • C后跟另一个UPPERCASE字母(另一个化学元素,即)=&gt; C

如果您能够安装另一个库,您可能会相处:

library("stringr")
strings <- c("C16H4ClNO2", "CH8O", "F2Ni")

str1 <- str_extract(strings, '(?<=C)\\d+')
str2 <- str_count(strings, 'C[A-Z]') 
str2[!is.na(str1)] = str1[!is.na(str1)]
str2
# [1] "16" "1"  "0" 

这有很多奇特的东西,str1寻找第一个条件(C后跟另一个数字),而str2寻找第二个条件。最后一行结合了两个向量

答案 2 :(得分:0)

我们可以使用base R

执行此操作
sub("C(\\d+).*", "\\1", sub("C([^0-9]+)", 
  "C1\\1", ifelse(!grepl("C", strings), paste0("C0", strings), strings)))
#[1] "16" "1"  "0" 

答案 3 :(得分:0)

ifelse(str_extract(strings,'(?<=C)(\\d+|)')=='',1,str_extract(strings,'(?<=C)(\\d+|)'))
[1] "16" "1"  NA