R 提取标点符号之间的字符串(如果存在)
我试图在R 提取标点符号之间的字符串(如果存在),r,regex,R,Regex,我试图在:或之后提取字符串和a之前如果第二个标点符号存在,则删除a之后的所有内容如果存在。目标结果是一个数字 当前代码可以在:和之间执行或之后的:但无法处理单独或:单独 另外,gsub(|(100);参见注释)不起作用,我不确定为什么初始的:没有被排除在外,并且需要gsub test以下是一些解决方案 前两个是基础。第一种方法只使用非常简单的正则表达式。第二个比较短,正则表达式只是稍微复杂一点。在这两种情况下,如果没有匹配项,我们都会返回NA,但如果对您很重要,您可以在之后使用0替换NAs(使用
:
或之后提取字符串代码>和a之前
如果第二个标点符号存在,则删除a之后的所有内容代码>如果存在。目标结果是一个数字
当前代码可以在:
和之间执行
或之后的:
但无法处理代码>单独或:
单独
另外,gsub(|(100);参见注释)
不起作用,我不确定为什么初始的:
没有被排除在外,并且需要gsub
test以下是一些解决方案
前两个是基础。第一种方法只使用非常简单的正则表达式。第二个比较短,正则表达式只是稍微复杂一点。在这两种情况下,如果没有匹配项,我们都会返回NA,但如果对您很重要,您可以在之后使用0替换NAs(使用ifelse(is.NA(x),0,x)
其中x
是NAs的答案)
第三个与第二个几乎相同,但在gsubfn中使用Straply。它返回0而不是NA
1)读取。表用分号替换所有冒号,并将其作为分号分隔的字段读取。选取第二个这样的字段,删除第一个非数字及其后的所有内容。然后将剩下的转换为数字
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
3)使用与(2)中相同的模式将匹配项转换为数字,如果匹配项为空,则返回0
library(gsubfn)
strapply(test, "^[^:;]+[;:] (\\d+)", as.numeric, simplify = TRUE, empty = 0)
## [1] 2 30 0
这里有一些解决方案
前两个是基础。第一种方法只使用非常简单的正则表达式。第二个比较短,正则表达式只是稍微复杂一点。在这两种情况下,如果没有匹配项,我们都会返回NA,但如果对您很重要,您可以在之后使用0替换NAs(使用ifelse(is.NA(x),0,x)
其中x
是NAs的答案)
第三个与第二个几乎相同,但在gsubfn中使用Straply。它返回0而不是NA
1)读取。表用分号替换所有冒号,并将其作为分号分隔的字段读取。选取第二个这样的字段,删除第一个非数字及其后的所有内容。然后将剩下的转换为数字
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
3)使用与(2)中相同的模式将匹配项转换为数字,如果匹配项为空,则返回0
library(gsubfn)
strapply(test, "^[^:;]+[;:] (\\d+)", as.numeric, simplify = TRUE, empty = 0)
## [1] 2 30 0
另一种方法:
out <- gsub('(^.+?[;:][^0-9]+)(\\d+)(.*$)|^.+', '\\2', test)
out[out == ''] <- 0
as.numeric(out)
## [1] 2 30 0
out另一种方法:
out <- gsub('(^.+?[;:][^0-9]+)(\\d+)(.*$)|^.+', '\\2', test)
out[out == ''] <- 0
as.numeric(out)
## [1] 2 30 0
out根据OP的描述(斜体是我的):
在:或之后提取字符串;在;如果出现第二个标点符号,则删除a之后的所有内容;如果有。目标结果是一个数字
我认为其他一些建议可能会忽略斜体字的标准。这是OP的测试集,在末尾有一个额外的条件来测试:
test<-c( "Score (ABC): 2 (of 100); see note",
"Amount of ABC; 30%",
"Presence of ABC: negative",
"...and before a ; if the second punctuation is present, then remove everything after a ; if present [so 666 should not be returned]")
符合OP要求的结果:
如果OP确实需要一个没有匹配项的带零整数,请将sub()替换设置为“'0\\1”
,并用包装为.integer()
,如下所示:
as.integer( gsub( pattern='.+?[:;]\\D*?[^;](\\d*).*?;*.*',
replacement='0\\1',
x=test, perl=TRUE) )
结果:
[1] 2 30 0 0
完全在线工作R(R 3.3.2)示例:
Regexp解释
OP只想在字符串中找到一个匹配项,这样sub()
函数就可以正常工作
使用<代码>子()/<代码>的方法是生成与所有字符串匹配的模式,但如果满足条件,则在中间使用捕获组捕获零个或更多个数字。p>
模式
+?[:;]\\D*?[^;](\\D*).*?;**代码>如下所示
+?
在一次和无限次之间匹配任何字符(行终止符除外)+
,?
尽可能少地匹配,根据需要扩展(惰性)
[:;]
在方括号之间匹配列表中的单个字符,在本例中为:
或代码>
\\D
匹配任何非数字字符(等于[^0-9])
*?
量词*
在零次和无限次之间匹配?
尽可能少的次数,根据需要展开(惰性)
[^;]
作为方括号之间的第一个字符的^
表示:在方括号之间匹配列表中不存在的单个字符,在这种情况下,匹配任何不属于的字符代码>
(\d*)
曲线括号之间的所有内容都是一个捕获组-这是第一个捕获组:\\d*
在零次和无限次之间匹配一个数字(等于[0-9]),尽可能多地匹配(贪婪)
*代码>匹配代码>字符*
介于零次和无限次之间[因此,不必存在,但如果存在则匹配:这是根据OP请求排除第二个分隔符之后的任何内容的关键]
*
在零次和无限次之间匹配任意字符*
,尽可能多地匹配(贪心)[因此将所有字符都拾取到行的末尾]
替换=\\1
指的是我们模式中的第一个捕获组。我们用我们在捕获组中发现的东西替换所有与模式匹配的东西<代码>\\d*
不能匹配任何数字,因此如果在我们期望的位置没有找到数字,则将返回空字符串。根据OP的描述(斜体是我的):
在:或之后提取字符串;在;如果出现第二个标点符号,则删除a之后的所有内容;如果有。目标结果是一个数字
我认为其他一些建议可能会忽略斜体字的标准。这是OP的测试集,在末尾有一个额外的条件来测试:
test<-c( "Score (ABC): 2 (of 100); see note",
"Amount of ABC; 30%",
"Presence of ABC: negative",
"...and before a ; if the second punctuation is present, then remove everything after a ; if present [so 666 should not be returned]")
符合OP要求的结果:
如果OP确实需要一个没有匹配项的带零整数,请将sub()替换设置为“'0\\1”
,并用包装为.integer()
,如下所示:
as.integer( gsub( pattern='.+?[:;]\\D*?[^;](\\d*).*?;*.*',
replacement='0\\1',
x=test, perl=TRUE) )
结果:
[1] 2 30 0 0
完全在线工作R(R 3.3.2)示例: