RegEx для захвата повторяющегося шаблона - PullRequest
1 голос
/ 03 июня 2019

У меня есть следующее регулярное выражение из регулярное выражение, захватывающее с повторяющимся узором

([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 ]

3 голосов
/ 03 июня 2019

Вы можете сделать эту работу только с небольшими изменениями, но проблема в том, что последняя часть.Общая форма закаленного жадного жетона такова:

(.(?!notAllowed))+

, поэтому, используя этот шаблон для вашего случая, добавьте именованные группы для ясности:

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

PS: если вы не можете включить режим «точка соответствует новой строке», вы можете использовать [\s\S] для симуляции.

regex101 demo

2 голосов
/ 03 июня 2019

Я не могу решить это с небольшими изменениями. Итак, я просто предлагаю свое решение:

([0-9]{1,2}h) *([0-9]{1,2}min):[\s\S]*?(?=[0-9]{1,2}h|$)
1 голос
/ 03 июня 2019

Требуемый результат довольно сложно сопоставить, но не невозможно.

Я бы сделал часть этого, возможно, часть времени и заголовка с помощью регулярных выражений, если все в порядке, то остальное с помощью сценариев.

Здесь мы можем начать с выражения, похожего на:

([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 Circuit

jex.im визуализирует регулярные выражения:

enter image description here

...