2016-11-10 44 views
1

的假设我有以下的字符串(文件名):提取物2份串

a <- "X/ZHEB100/TKN_VAR29380_timely_p1.txt" 

其中由几部分组成(这里给出P1)

或另一个

b <- "X/ZHEB100/ZHN_VAR29380_timely.txt" 

它只包含一个部分(所以不需要标记任何p)

如何提取标识符,这是VARXXXXX之前的三个字母(如果一个是TKN,如果两个是ZHN)加上零件标识符(如果可用)?

所以结果应该是:

case1 : TKN_p1 
case2 : ZHN 

我知道如何提取的第一标识,但我无法处理在同一时间的第二个。

我迄今为止的做法:

sub(".*(.{3})_VAR29380_timely(.{3}).*","\\1\\2", a) 
sub(".*(.{3})_VAR29380_timely(.{3}).*","\\1\\2", b) 

但这种不正确的增加.tx在第二种情况下。

+0

尝试'子(“^ * /([AZ] {3})_ [^/_] + _ [^/_] +(_ [^ _。/] +)?\\。[^。] * $“,”\\ 1 \\ 2“,a)' –

+0

也许先测试一个标识符,例如'stringr :: str_match(string,'_p。\\。txt')'然后使用两个更简单的正则表达式? –

+0

@WiktorStribiżew不适用于第二种情况。 – user3032689

回答

2

您未使用锚点并匹配timely之后的最后3个字符,但未检查这些字符是什么(.与任何字符匹配)。

我建议

sub("^.*/([A-Z]{3})_VAR\\d+_timely(_[^_.]+)?\\.[^.]*$", "\\1\\2", a) 

详细

  • ^ - 字符串的开始
  • .*/ - 字符串的一部分截至及包括最后/
  • ([A-Z]{3}) - 3 ASCII大写字母捕获int Ô1个
  • _VAR\\d+_timely - _VAR + 1或多个数字+ _timely
  • (_[^_.]+)? - 任选的组2捕获_ + 1或更多个字符比_.
  • \\.其他 - 点
  • [^.]* - 零或更多的字符.
  • $ - 字符串结尾。

替换模式包含2个反向引用到两个捕获组以将其内容插入替换的字符串。

R demo

a <- "X/ZHEB100/TKN_VAR29380_timely_p1.txt" 
a2 <- sub("^.*/([A-Z]{3})_VAR\\d+_timely(_[^_.]+)?\\.[^.]*$", "\\1\\2", a) 
a2 
[1] "TKN_p1" 
b <- "X/ZHEB100/ZHN_VAR29380_timely.txt" 
b2 <- sub("^.*/([A-Z]{3})_VAR\\d+_timely(_[^_.]+)?\\.[^.]*$", "\\1\\2", b) 
b2 
[1] "ZHN" 
+0

此外,[这里是一个正则表达式演示](https://regex101.com/r/HjM4dl/1)。 –

1

又一个解决方案,从Wiktor的公司已经开始着手解决方案不同的东西:

library(magrittr) 
data <- c(a, b) 

首先通过 “/” 分裂拿到 “身份证” 的价值观,以最后值,并取前3个字符:

ID <- strsplit(data, "/") %>% 
    sapply(tail, n = 1) %>% 
    substr(1, 3) 

Th EN通过拆分出两个“及时”和“.TXT”获得“部分”的价值观,并采取最后一个元素(这可能是一个空字符串):

part <- strsplit(data, "timely|.txt") %>% 
    sapply(tail, n = 1) 

现在只需将其粘贴在一起的结果:

output <- paste0(ID, part) 
output 
[1] "TKN_p1" "ZHN" 

或者,如果你不想创建中间对象:

output <- strsplit(data, "/") %>% 
    sapply(tail, n = 1) %>% 
    substr(1, 3) %>% 
    paste0(strsplit(data, "timely|.txt") %>% 
         sapply(tail, n = 1))