Как захватить все, пока не появится другая группа захвата - PullRequest
2 голосов
/ 03 июня 2019

У меня есть следующий шаблон:

1251 Left Random Text I want to fill  
It can go through multiple lines  
As you can see  
9841 Right Again we see a lot of random text with 3115 numbers  
And this also goes  
To multiple lines  
0121 Right    
5151 Right This one is just one line  
I was wrong  
9731 Left This one is just a line  
5123 NA Instruction 5151 was wrong  
4113 Right Instr 9841 was correct  
We checked  

Я хочу иметь 3 группы:

1251  

Left  

Random Text I want to fill  
It can go through multiple lines  
As you can see  

Я использую

(\d+)\s(\w+)\s(.*)  

но он останавливается только на текущей строке (поэтому я получаю только Random Text I want to fill в группе 3, хотя я хочу включить As you can see)
Если я использую однострочный флаг, я получаю только 1 совпадение для каждой группы, группы 3почти все

Вот вживую: https://regex101.com/r/W3x0mH/4

Ответы [ 4 ]

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

Вы можете использовать повторяющуюся группу, соответствующую всем строкам, утверждая, что следующая строка не начинается с цифр 1+, за которыми следуют Левая или Правая:

(\d+)\s(\w+)\s(.*(?:\r?\n(?!\d).*)*)

Объяснение

  • (\d+)\s(\w+)\s Соответствие первым 2 группам
  • ( Третья группа захвата
    • .* Соответствие 0+ раз любому символу, кроме новой строки
    • (?: Группа без захвата \r?\n(?!\d).* Совпадение с новой строкой, утверждение, что справа не цифра
    • )* Закрыть группу без захвата и повторить 0+ раз
  • ) Закрыть группу захвата

Regex demo

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

Вы можете использовать это регулярное выражение с предвидением:

^(\d+)\s(\w+)\s(.*?)(?=\n\d|\z)

с модификаторами DOTALL и MULTILINE.

Обновленное демо-выражение Regex

Подробности RegEx:

  • ^: начало строки
  • (\d+): сопоставление и захват 1+ цифр в группе # 1
  • \s: сопоставить пробел
  • (\w+): сопоставить и перехватить символы 1+ слова в группе # 2
  • \s: сопоставить пробел
  • (.*?): сопоставить0 или более любых символов (не жадных), если при следующем заявлении в виде предварительного просмотра используется satiSfied
  • (?=\n\d|\z): утверждение в виде предварительного просмотра, подтверждающее, что у нас есть новая строка, за которой следует цифра или конец ввода

Более быстрое регулярное выражение:

Если вы используете это регулярное выражение для длинной строки, то вам также следует помнить общую производительность какрегулярное выражение с модификатором DOTALL будет иметь тенденцию замедляться для текста большого размера.Для этого я предлагаю использовать это регулярное выражение, которое не нуждается в модификаторе DOTALL:

^(\d+)\s(\w+)\s(.*(?:\n.*)*?)(?=\n\d|\z)

RegEx Demo 2

На демонстрационном примере regex101 это регулярное выражение занимает всего 181 шагов по сравнению с первым шагом 1300 шагов .

1 голос
/ 03 июня 2019

Для третьей группы повторите любой символ, используя отрицательный прогноз для ^\d, что указывает на начало нового совпадения:

(\d+)\s(\w+)\s((?:(?!^\d)[\s\S])*)

https://regex101.com/r/W3x0mH/5

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

Вы можете попробовать это регулярное выражение:

^(\d+)\s+(\w+)\s+(.*?)(?=^\d|\z)
  1. ^(\d+)\s+, ^\d+ Строка начинается с цифр, за которыми следует один или несколько пробельных символов \s+
  2. (\w+)\s+, где \w+ один или несколько символов (влево, вправо, na или что-то еще), за которыми следует один или несколько пробелов \w+
  3. (.*?) соответствует всему, пока не будет найдена строка, начинающаяся с цифры или \z конец строки.

Я думаю, что это соответствует вашему требованию ....

Regex101

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...