Требуется помощь в составлении регулярного выражения
Требуется помощь гуру по регулярным выражениям, имеется текст:
Техническая информация
Дата
Время
Документ № 1
Подпись
Дата 10.08.2020
Какой-то текст
1/10
Техническая информация
Дата
Время
Документ № 2
Подпись
Дата 16.09.2020
Снова какой-то текст
2/10
...
Подскажите, как составить регулярное выражение, чтобы получить определенную информацию (позиция и номер), слово "Документ" повторяется? В итоге хочу получить все номера документов и позиции этих документов, т.е. номер документ 1 и позиция 1/10, номер документа 2 и позиция у него 2/10...
Ответы (2 шт):
Как-то так, думаю: Документ № (?<number>\d+)\s+(?<signature>[^\n]+)\s*Дата\s*(?<date>\d{2}\.\d{2}\.\d{4})\s*(?<text>.*?)\s+(?<position>\d+\/\d+). Предполагается, что подпись не содержит переводов строк. Обратите внимание на нежадный захват в тексте.
Ссылка на тест.
Перенесу ответ в комментарии:
Документ №\h*(\d+)[\S\s]*?(\d+\/\d+)
И немного попытаюсь объяснить подробнее
Данным regexp мы ищем совпадения от вхождения "Документ" и до "одна и более цифр/одна и более цифр":
Документ № 1
Подпись
Дата 10.08.2020
Какой-то текст
1/10
Техническая информация
Дата
Время
Документ № 2
Подпись
Дата 16.09.2020
Снова какой-то текст
2/10
Это полное совпадение которое захватывает регулярное выражение, но, у нас в шаблоне есть группы захвата, данные в круглых скобках (...) Их можно получить отдельно.
В первой группе \1 будет хранится номер документа, во второй группе \2 будет позиция.
Именно эти группы и нужно использовать далее, так как в C# я не силен, то приведу пример со страницы документации docs.microsoft.com:
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"Документ №\h*(\d)[\S\s]*?(?:(\d+\/\d+)|(?=Документ))";
string input = "Техническая информация
Дата
Время
Документ № 1
Подпись
Дата 10.08.2020
Какой-то текст
1/10
Техническая информация
Дата
Время
Документ № 2
Подпись
Дата 16.09.2020
Снова какой-то текст
2/10
";
MatchCollection matches = Regex.Matches(input, pattern);
foreach (Match match in matches)
{
Console.WriteLine("DOC: {0}", match.Groups[1].Value);
Console.WriteLine("POZ: {0}", match.Groups[2].Value);
Console.WriteLine();
}
Console.WriteLine();
}
}
________
// The example displays the following output:
// DOC: 1
// POZ: 1/10
//
// DOC: 2
// POZ: 2/10
//
О самом регулярном выражении:
Документ №\h* - текс Документ № и ноль и более горизонтальных пробельных символов
(\d+) - одна и более цифр захватываемых в группу 1
[\S\s]*? - ноль и более любых пробельных и не пробельных символов, где *? - ленивый квантификатор, который остановится при ближайшем подходящем совпадении
(\d+\/\d+) - вторая захватываемая группа, где одна и более цифры указанны через / и далее еще одна и более цифра.
С осторожностью!
В случае если в тексте не будет указана позиция, то выполнение будет проходить до следующего совпадения, т.е. данные шаблон подойдет, если в тексте гарантированно будет для каждого документа указанная позиция.
Если позиция может быть не указана, то следует указать в шаблоне, что бы проверка для данного текста останавливалась при достижении текста "Докумен"
Документ №\h*(\d)[\S\s]*?(?:(\d+\/\d+)|(?=Документ))
Пример работы: regex101