如何在R中首次出现两个字符之间获取模式?

时间:2016-04-05 16:57:23

标签: regex r pattern-matching

我正在尝试匹配一个模式:VD=与字符串中第一次出现|之间的任何内容,比如tmp,如下所示:

tmp <- "PC=I;RS=128850544;RE=128850566;LEN=6;S1=36;S2=499.417;REP=2;VT=Ins;VD=SMO|CCDS5811.1|r.?|-|-|protein_coding:CDS:intron:insertion:intron_variant|SO:0000010:SO:0000316:SO:0000188:SO:0000667:SO:0001627;VC=intronic;VW=SMO|CCDS5811.1|r.?|-|-|protein_coding:CDS:intron:insertion:intron_variant|SO:0000010:SO:0000316:SO:0000188:SO:0000667:SO:0001627"

gene <- sub("^.*VD=([A-Za-z0-9]+)[|].*", "\\1", tmp)
gene
# [1] "SMO"

但是当字符串中没有VD=|时,它会抓取整个字符串:

tmp <- "PC=D;RS=72450731;RE=72450735;LEN=1;S1=72;S2=802.939;REP=3;VT=Del"

gene <- sub("^.*VD=([A-Za-z0-9]+)[|].*", "\\1", tmp)
gene
# [1] "PC=D;RS=72450731;RE=72450735;LEN=1;S1=72;S2=802.939;REP=3;VT=Del"

即使没有NAVD=个字符,我也不明白为什么它会抓取整个字符串而不是|。有没有办法在第一次出现两个字符之间抓取一个模式并打印它,如果没有找到模式则打印NA。

非常感谢任何帮助。

谢谢!

2 个答案:

答案 0 :(得分:4)

你的正则表达式看起来很复杂。使用像这样的简单正则表达式

正则表达式: VD=([^|]+)就足够了。使用\\1进行反向引用。

说明: ([^|]+)匹配从VD=到遇到第一个|的任何内容。

<强> Regex101 Demo

tmp <- c("PC=D;RS=72450731;RE=72450735;LEN=1;S1=72;S2=802.939;REP=3;VT=Del", "PC=I;RS=128850544;RE=128850566;LEN=6;S1=36;S2=499.417;REP=2;VT=Ins;VD=SMO|CCDS5811.1|r.?|-|-|protein_coding:CDS:intron:insertion:intron_variant|SO:0000010:SO:0000316:SO:0000188:SO:0000667:SO:0001627;VC=intronic;VW=SMO|CCDS5811.1|r.?|-|-|protein_coding:CDS:intron:insertion:intron_variant|SO:0000010:SO:0000316:SO:0000188:SO:0000667:SO:0001627")
gsub('VD=([^|]+)|.', '\\1', tmp)
# [1] ""    "SMO"

答案 1 :(得分:1)

我认为你有效地尝试解析多级分隔的字符串。我建议不要尝试使用单个正则表达式来提取所需的信息,而是使用更严格的逐步细分语法元素。

首先,您可以拆分分号以获得看起来像变量赋值的顶级部分:

tmp <- 'PC=I;RS=128850544;RE=128850566;LEN=6;S1=36;S2=499.417;REP=2;VT=Ins;VD=SMO|CCDS5811.1|r.?|-|-|protein_coding:CDS:intron:insertion:intron_variant|SO:0000010:SO:0000316:SO:0000188:SO:0000667:SO:0001627;VC=intronic;VW=SMO|CCDS5811.1|r.?|-|-|protein_coding:CDS:intron:insertion:intron_variant|SO:0000010:SO:0000316:SO:0000188:SO:0000667:SO:0001627';
specs <- strsplit(fixed=T,tmp,';')[[1L]];
specs;
##  [1] "PC=I"
##  [2] "RS=128850544"
##  [3] "RE=128850566"
##  [4] "LEN=6"
##  [5] "S1=36"
##  [6] "S2=499.417"
##  [7] "REP=2"
##  [8] "VT=Ins"
##  [9] "VD=SMO|CCDS5811.1|r.?|-|-|protein_coding:CDS:intron:insertion:intron_variant|SO:0000010:SO:0000316:SO:0000188:SO:0000667:SO:0001627"
## [10] "VC=intronic"
## [11] "VW=SMO|CCDS5811.1|r.?|-|-|protein_coding:CDS:intron:insertion:intron_variant|SO:0000010:SO:0000316:SO:0000188:SO:0000667:SO:0001627"

接下来,您可以搜索感兴趣的LHS,只提取第一次出现(如果有多个匹配):

vdspec <- grep(perl=T,value=T,'^VD=',specs)[1L];
vdspec;
## [1] "VD=SMO|CCDS5811.1|r.?|-|-|protein_coding:CDS:intron:insertion:intron_variant|SO:0000010:SO:0000316:SO:0000188:SO:0000667:SO:0001627"

您可以深入查看RHS,然后将其拆分为竖线分隔的字段:

vd <- sub(perl=T,'^VD=','',vdspec);
vd;
## [1] "SMO|CCDS5811.1|r.?|-|-|protein_coding:CDS:intron:insertion:intron_variant|SO:0000010:SO:0000316:SO:0000188:SO:0000667:SO:0001627"
vdfields <- strsplit(fixed=T,vd,'|')[[1L]];
vdfields;
## [1] "SMO"
## [2] "CCDS5811.1"
## [3] "r.?"
## [4] "-"
## [5] "-"
## [6] "protein_coding:CDS:intron:insertion:intron_variant"
## [7] "SO:0000010:SO:0000316:SO:0000188:SO:0000667:SO:0001627"

现在,您可以轻松获得您正在寻找的价值:

vdfields[1L];
## [1] "SMO"

如果您的目标LHS不匹配,您将从NA来电中获得grep()[1L]

xxspec <- grep(perl=T,value=T,'^XX=',specs)[1L];
xxspec;
## [1] NA

因此,您可以对grep()[1L]调用的结果进行分支,以处理缺少LHS的情况。