正则表达式,用于分割具有多个捕获组的单词列表

时间:2019-05-19 23:16:12

标签: r regex regex-lookarounds regex-group regex-greedy

我有以下字符串:

one two three four five six seven eight nine

我正在尝试构造一个将字符串分为三类的正则表达式:

  1. 第1组:“一二三”
  2. 第2组:“四个五个六个”
  3. 第3组:“七八九”

我尝试了(.*\b(one|two|three)?)(.*\b(four|five|six)?)(.*\b(seven|eight|nine)?)的变体,但是这种模式将完全匹配项分成一个包含完整字符串的组-the demo can be found here

尝试(.*\b(one|two|three))(.*\b(four|five|six))(.*\b(seven|eight|nine))可以使我更接近我想要的东西,但是比赛信息面板显示该模式可识别两个比赛,每个比赛包含六个捕获组。

我正在使用OR语句,因为组的长度可以任意,例如two three four,将模式应用于此字符串应标识两组-

  1. 第1组:“两个”
  2. 第2组:“三个”。

3 个答案:

答案 0 :(得分:2)

可能会做的大型正则表达式

(?=.*\b(?:one|two|three|four|five|six|seven|eight|nine)\b)(\b(?:one|two|three)(?:\s+(?:one|two|three))*\b)?.+?(\b(?:four|five|six)(?:\s+(?:four|five|six))*\b)?.+?(\b(?:seven|eight|nine)(?:\s+(?:seven|eight|nine))*\b)?

https://regex101.com/r/rUtkyU/1

可读版本

 (?=
      .* \b 
      (?:
           one
        |  two
        |  three
        |  four
        |  five
        |  six
        |  seven
        |  eight
        |  nine
      )
      \b 
 )
 (                             # (1 start)
      \b   
      (?: one | two | three )

      (?:
           \s+ 
           (?: one | two | three )
      )*
      \b 
 )?                            # (1 end)

 .+? 
 (                             # (2 start)
      \b        
      (?: four | five | six )

      (?:
           \s+ 
           (?: four | five | six )
      )*
      \b     
 )?                            # (2 end)

 .+?   
 (                             # (3 start)
      \b          
      (?: seven | eight | nine )

      (?:
           \s+ 
           (?: seven | eight | nine )
      )*
      \b   
 )?                            # (3 end)

答案 1 :(得分:1)

此答案假设您要一次查找三个数字单词组成的组:

x <- c("one two three four five six seven eight nine")
regexp <- gregexpr("\\S+(?:\\s+\\S+){2}", x)
regmatches(x, regexp)[[1]]

[1] "one two three"    "four five six"    "seven eight nine"

如果您想要一个更通用的解决方案,而不需要先验地知道输入的长度是多少(即,存在三个一组的多少个组),那么您可能必须使用迭代方法:

parts <- strsplit(x, " ")[[1]]
output <- character(0)
for (i in seq(from=1, to=length(parts), by=3)) {
    output <- c(output, paste(parts[i], parts[i+1], parts[i+2]))
}
output

[1] "one two three"    "four five six"    "seven eight nine"

答案 2 :(得分:0)

我不太确定您想要的输出是什么。但是,此表达式通过并创建了几个单独的捕获组,以使其易于调用:

((one|two|three)\s.*?)((four|five|six)\s.*?)((seven|eight|nine)\s.*)

enter image description here

RegEx

如果不需要此表达式,则可以在regex101.com中修改/更改表达式。

RegEx电路

您还可以在jex.im中可视化您的表达式:

enter image description here

JavaScript演示

此代码段显示各种捕获组可能返回的内容:

const regex = /((one|two|three)\s.*?)((four|five|six)\s.*?)((seven|eight|nine)\s.*)/gm;
const str = `one two three four five six seven eight nine

two three four six seven eight`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}