首页 > 解决方案 > 在标点符号之间提取字符串(如果存在)

问题描述

如果存在第二个标点符号,我试图在 a 之后:或a;之前提取一个字符串;,然后在 a 之后删除所有内容;。目标结果是一个数字。

当前代码能够在:;之后进行 OR操作,:但不能;单独或:单独处理。

此外,gsub(|(OF 100); SEE NOTE)它不起作用,我不确定为什么:不排除初始值并且根本需要 gsub。

test<-c("Score (ABC): 2 (of 100); see note","Amount of ABC; 30%","Presence of ABC: negative","ABC not tested") 
#works for :/;
toupper((regmatches(toupper(test), gregexpr(":\\s* \\K.*?(?=;)", toupper(test), perl=TRUE))))
#works for :
test<-toupper((regmatches(toupper(test), gregexpr(":\\s* (.*)", toupper(test), perl=TRUE))))
#removes extra characters:
test<-gsub(": |(OF 100); SEE NOTE|%|; ","",test)
#Negative to numeric:
test[grepl("NEGATIVE|<1",test)]<-0
test

预期结果:2 30 0

标签: rregex

解决方案


这里有一些解决方案。

前两个是基础。第一个只使用非常简单的正则表达式。第二个更短,正则表达式只是稍微复杂一点。在这两种情况下,如果没有匹配项,我们将返回 NA,但如果这对您很重要,您可以在之后将 NA 替换为 0(使用NAifelse(is.na(x), 0, x)x答案)。

第三个与第二个几乎相同,但在 gsubfn 中使用了 strapply。它返回 0 而不是 NA。

1) read.table用分号替换所有冒号,并将其作为分号分隔的字段读入。选择第二个这样的字段并删除第一个非数字及其之后的所有内容。然后将剩下的转换为数字。

DF <- read.table(text = gsub(":", ";", test), 
  as.is = TRUE, fill = TRUE, sep = ";", strip.white = TRUE)
as.numeric(sub("\\D.*", "", DF$V2))
##[1]  2 30 NA

2) strcapture 从不是冒号或分号的起始字符开始匹配,然后匹配冒号或分号,然后匹配空格,最后捕获数字。返回转换为数字的捕获数字。

strcapture("^[^:;]+[;:] (\\d+)", test, list(num = numeric(0)))$num
##[1]  2 30 NA

3) strapply 使用与 (2) 中相同的模式将匹配转换为数字,如果匹配为空则返回 0。

library(gsubfn)
strapply(test, "^[^:;]+[;:] (\\d+)", as.numeric, simplify = TRUE, empty = 0)
## [1]  2 30  0

推荐阅读