正则表达式用于捕获重复模式

时间:2019-06-03 04:09:59

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

我有来自regex capturing with repeating pattern的以下正则表达式

([0-9]{1,2}h)[ ]*([0-9]{1,2}min):[ ]*(.*(?:\n(?![0-9]{1,2}h).*)*)

它需要以下字符串

1h 30min: Title 
- Description Line 1
1h 30min: Title
- Description Line 1
- Description Line 2
- Description Line 3

并产生此结果

Match 1:
  "1h 30min: Title 
  - Description Line 1"

      Group 1: "1h"
      Group 2: "30min"
      Group 3: "Title 
               - Description Line 1"

Match 2:
  "1h 30min: Title 
 - Description Line 1
 - Description Line 2
 - Description Line 3"

      Group 1: "1h"
      Group 2: "30min"
      Group 3: "Title 
               - Description Line 1
               - Description Line 2
               - Description Line 3"

我现在有匹配的1h 30min并不总是出现在新行上。所以说我有以下字符串

1h 30min: Title 
- Description Line 1 1h 30min: Title - Description Line 1
- Description Line 2
- Description Line 3

如何修改正则表达式以获取以下匹配结果?

Match 1:
  "1h 30min: Title 
  - Description Line 1"

      Group 1: "1h"
      Group 2: "30min"
      Group 3: "Title 
               - Description Line 1"

Match 2:
  "1h 30min: Title - Description Line 1
 - Description Line 2
 - Description Line 3"

      Group 1: "1h"
      Group 2: "30min"
      Group 3: "Title - Description Line 1
               - Description Line 2
               - Description Line 3"

我虽然删除了\n可以解决问题,但最终只匹配第一个1h 30min之后的所有内容

3 个答案:

答案 0 :(得分:3)

您仅需进行很小的更改就可以使它起作用,但问题是最后一部分。 tempered greedy token的一般形式是:

(.(?!notAllowed))+

因此,针对您的情况使用此模式,并添加命名组以使内容更清晰:

(?<hours>[0-9]{1,2}h)[ ]*(?<minutes>[0-9]{1,2}min):\s*(?<description>(?:.(?!\dh\s\d{1,2}min))+)

PS:如果无法打开“点匹配换行符”模式,则可以use [\s\S]进行模拟。

regex101 demo

答案 1 :(得分:2)

我无法通过较小的更改来解决它。 所以,我只提供我的解决方案:

([0-9]{1,2}h) *([0-9]{1,2}min):[\s\S]*?(?=[0-9]{1,2}h|$)

答案 2 :(得分:1)

所需的输出很难匹配,但并非不可能。

我会做一部分,也许时间和标题部分用正则表达式,如果可以的话,其余部分用脚本编写。

在这里,我们可以从类似于以下内容的表达式开始

([0-9]{1,2}h)\s+([0-9]{1,2}min):\s+(Title)([\d\D]*?\d|.+)|[\s\S]*

或:

([0-9]{1,2}h)\s+([0-9]{1,2}min):\s+([A-Za-z\s]+)([\d\D]*?\d|.+)|[\s\S]*

const regex = /([0-9]{1,2}h)\s+([0-9]{1,2}min):\s+(Title)([\d\D]*?\d|.+)|[\s\S]*/gm;
const str = `1h 30min: Title 
- Description Line 1 1h 30min: Title - Description Line 1
- Description Line 2
- Description Line 3`;
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}`);
    });
}

RegEx电路

jex.im可视化正则表达式:

enter image description here