正则表达式-捕获重复的组,但不包括周围的部分匹配内容

时间:2018-08-15 12:58:39

标签: r regex pcre repeat

出于记录,我正在使用R,但是我拥有的查询是独立于平台的(按现状),因此我将使用regex101进行演示。我正在尝试捕获可能被其他文本包围或不被其他文本包围的重复组。因此,此演示中显示了理想的行为: demo1

regex:(\d{2})(AB)

文本:blahblah11AB12AB13ABblah

因此它很好地捕获了我想要的所有组:

第1场

Full match  8-12    `11AB`
Group 1.    8-10    `11`
Group 2.    10-12   `AB`

比赛2

Full match  12-16   `12AB`
Group 1.    12-14   `12`
Group 2.    14-16   `AB`

第3场

Full match  16-20   `13AB`
Group 1.    16-18   `13`
Group 2.    18-20   `AB`

但是,如果我包含另一段匹配的文本,它也会捕获到该文本(我想这很公平)

文本:blahblah11AB12AB13ABblah22AB 返回相同但带有额外的组:

第4场

Full match  24-28   `22AB`
Group 1.    24-26   `22`
Group 2.    26-28   `AB`

demo2

我想做的是捕获第一个组,但是忽略所有其他文本,即使有后续匹配也是如此。本质上,我只想从该文本中获得三个匹配项:blahblah11AB12AB13ABblah22AB

我尝试了很多事情,例如: (((\d{2})(AB))+)(.*)

但是随后我得到以下信息,它丢失了最后一组捕获的所有信息:

Demo 3

第1场

Full match  8-28    `11AB12AB13ABblah22AB`
Group 1.    8-20    `11AB12AB13AB`
Group 2.    16-20   `13AB`
Group 3.    16-18   `13`
Group 4.    18-20   `AB`
Group 5.    20-28   `blah22AB`

我需要保留重复小组的东西。难过!

在R中,输出应如下所示:

[[1]]
     [,1]   [,2] [,3]
[1,] "11AB" "11" "AB"
[2,] "12AB" "12" "AB"
[3,] "13AB" "13" "AB"

预先感谢...

3 个答案:

答案 0 :(得分:1)

一个想法是从use \G for chaining matches^开始,之后reset by \K

(?:^.*?\K|\G)(\d{2})(AB)
  • ^.*?\K将在第一个匹配项之前延迟匹配任意数量的任何字符
  • |\G或在上一场比赛的末尾继续,可以是:开始,第一,上一个

See your updated demo

这将匹配第一个匹配项,并且是pcre模式(perl=TRUE)。
如果在第一次匹配之前只能有非数字,请在^.*?\K中的use ^\D*\K instead

答案 1 :(得分:0)

如果我理解正确,则问题出在括号的位置。

pattern <- "(\\d{2}AB)"

s <- "blahblah11AB12AB13ABbla"

m <- gregexpr(pattern, s)
regmatches(s, m)
#[[1]]
#[1] "11AB" "12AB" "13AB"


s2 <- "blahblah11AB12AB13ABblah22AB"
s3 <- "11AB12AB13ABblah22AB"

S <- c(s, s2, s3)

m <- gregexpr(pattern, S)
regmatches(S, m)
#[[1]]
#[1] "11AB" "12AB" "13AB"
#
#[[2]]
#[1] "11AB" "12AB" "13AB" "22AB"
#
#[[3]]
#[1] "11AB" "12AB" "13AB" "22AB"

请注意,很多情况下,此操作仅在一条代码行中运行。我把它留下来是为了使它更清楚。

编辑。

也许以下是OP所要求的。
我敢打赌,有更好的解决方案,在我看来,两个正则表达式太过分了。

pattern <- "((\\d{2}AB)+)([^[:digit:]AB]+(\\d{2}AB))"
pattern2 <- "(\\d{2}AB)"

m <- gregexpr(pattern2, gsub(pattern, "\\1", S))
regmatches(S, m)
#[[1]]
#[1] "11AB" "12AB" "13AB"
#
#[[2]]
#[1] "11AB" "12AB" "13AB"
#
#[[3]]
#[1] "11AB" "12AB" "13AB"

答案 2 :(得分:0)

您可以使用量词config.trigger.after :halt do |x| machID = "./.vagrant/machines/default/virtualbox/id" if File.file?(machID) machineID = File.read(".vagrant/machines/default/virtualbox/id") end if defined?(machineID) x.run = {inline: "VBoxManage storageattach '#{machineID}' --storagectl 'IDE' --port 1 --device 0 --type hdd --medium none"} end config.trigger.before :destroy do |x| x.name = "Halting machine" x.run = {inline: "vagrant halt default"} end 来获得3个第一组:{3}。参见demo