返回特定字母后面的数字直到下一个字母的正则表达式
Posted
技术标签:
【中文标题】返回特定字母后面的数字直到下一个字母的正则表达式【英文标题】:Regular expression that returns numbers following a specific letter until the next letter 【发布时间】:2017-07-29 06:46:29 【问题描述】:我需要一个正则表达式,它返回一个特定的字母和后面的(一个或两个)数字,直到下一个字母。 例如,我想使用 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 的最终位置。
【问题讨论】:
是正则表达式要求吗?有更简单的解决方案,但它们的适用性取决于您的实际问题。最简单的是在记事本++中打开该文本,打开搜索窗口类型 C 并单击计数 - 如果确实需要,您可以在那里设置更多规则甚至使用正则表达式;对于软件类型应用程序,我会使用 python,读取 var 中的所有文本并在 var 中查找内容 对不起 - 问题可能被误解了 您可以检查 regex101.com 并在那里进行测试,但作为建议,您可以使用 [AZ] 或 [a-zA-Z] 而不是整个字母表,如果包含的小写字母也是 \d 所以C\d+ 会找到你需要的一切 你可以做sub("C(\\d+).*", "\\1", sub("C([^0-9]+)", "C1\\1", ifelse(!grepl("C", strings), paste0("C0", strings), strings))) #[1] "16" "1" "0"
谢谢,德拉科。我没有使用整个字母表:例如,我不想使用 C - 我如何排除 C?我想在 R 中使用正则表达式。我的真实数据集是两个合并的数据框,其中包含化学化合物,我想从它们的公式中计算某些元素。
【参考方案1】:
如果我正确理解了您的问题,那么您正在寻找两件事:
C + 紧随其后的一个数字 => 匹配这个数字 C 后跟另一个大写字母(即另一个化学元素)=> count 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】:我们可以通过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】: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)
添加到每个列表组件中,我们可以避免必须测试是否存在碳,从而产生以下(1) 中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) 的变体,它通过使用 makeup
将接受矩阵这一事实消除了 lapply
:
sapply(makeup(as.matrix(paste0(strings, "C0"))), "[[", "C")
## [1] 16 1 0
【讨论】:
【参考方案4】:ifelse(str_extract(strings,'(?<=C)(\\d+|)')=='',1,str_extract(strings,'(?<=C)(\\d+|)'))
[1] "16" "1" NA
【讨论】:
请不要发布纯代码答案。您可以通过解释它的工作原理或为什么它比替代方案更好来改进您的答案。以上是关于返回特定字母后面的数字直到下一个字母的正则表达式的主要内容,如果未能解决你的问题,请参考以下文章