#regex #find-occurrences
#регулярное выражение #найти-вхождения
Вопрос:
У меня есть следующие таблицы из результата dotnet test
команды, и чего я пытаюсь добиться, так это получения второго вхождения (тех, что ниже ветви) строк, которые начинаются со среднего значения.
--------- ----------- ----------- -----------
| | Line | Branch | Method |
--------- ----------- ----------- -----------
| Total | 100% | 100% | 100% |
--------- ----------- ----------- -----------
| Average | 100% | 100% | 100% |
--------- ----------- ----------- -----------
--------- ----------- ----------- -----------
| | Line | Branch | Method |
--------- ----------- ----------- -----------
| Total | 100% | 100% | 100% |
--------- ----------- ----------- -----------
| Average | 100% | 100% | 100% |
--------- ----------- ----------- -----------
Мне удалось написать следующее регулярное выражение, ^| Average *| (d .d %).*$
но добавление {2}
в любом месте выражения по-прежнему не возвращает мне второе вхождение. Кроме того, я пробовал использовать https://regex101.com / но информация о совпадении, которую оно показывает, следующая:
Насколько я понимаю, мне нужно получить вторую группу, но я думаю, что мне нужна подсказка или небольшая помощь для достижения моей цели.
Любая помощь? Заранее спасибо!
Комментарии:
1. Если я правильно понимаю, что вы хотите, вам просто нужно получить второе совпадение (и группу 1 внутри этого совпадения).
2. Точно. Я хочу, чтобы второе совпадение / вхождение 100% было более точным. Но я не могу понять, почему {2} не выполнило бы эту работу :-??
3. Куда вы пытаетесь добавить
{2}
?4. Ах, хорошо, в вашем случае вам не нужно изменять регулярное выражение, вам нужно найти совпадения, затем получить только второе. В regex101 вы можете нажать «генератор кода» -> «python», вы увидите пример того, как получить совпадения / группы. По сути, вы будете использовать
re.finditer
, а затем выполнять итерацию поmatches
(я использую имя переменной, которое regex101 использует в этом случае).5. В этом случае это немного сложнее, и вам нужно будет сделать две вещи: 1) сделайте так, чтобы ваше регулярное выражение охватывало несколько строк (я не помню параметр, возможно, » s»), 2) найдите вхождение вашего шаблона, которому предшествует другое вхождение того же шаблона. По крайней мере, это единственное решение, которое я вижу.
Ответ №1:
Как насчет этого:
string table =
" --------- ----------- ----------- ----------- " Environment.NewLine
"| | Line | Branch | Method |" Environment.NewLine
" --------- ----------- ----------- ----------- " Environment.NewLine
"| Total | 100% | 100% | 100% |" Environment.NewLine
" --------- ----------- ----------- ----------- " Environment.NewLine
"| Average | 100% | 89% | 100% |" Environment.NewLine
" --------- ----------- ----------- ----------- " Environment.NewLine
"" Environment.NewLine
" --------- ----------- ----------- ----------- " Environment.NewLine
"| | Line | Branch | Method |" Environment.NewLine
" --------- ----------- ----------- ----------- " Environment.NewLine
"| Total | 100% | 100% | 100% |" Environment.NewLine
" --------- ----------- ----------- ----------- " Environment.NewLine
"| Average | 100% | 99% | 100% |" Environment.NewLine
" --------- ----------- ----------- ----------- ";
MatchCollection matches = Regex.Matches(table, @"(?<=| Average *| d % | *)d %(?=.*)");
foreach (Match m in matches)
{
Console.WriteLine(m.Value);
}
Выводит:
89%
99%
Обновить:
Мне пришлось выяснить, что .NET (где я создал свое регулярное выражение) поддерживает кванторы в поисковых выражениях, в то время как в других реализациях регулярных выражений эта поддержка отсутствует.
Поэтому регулярное выражение моего решения не будет выполняться там.
Чтобы решить эту проблему, я удалил кванторы и заменил их объявлениями с фиксированными символами. Это работает для фиксированной таблицы, но не будет работать, если макет таблицы является динамическим по своей ширине:
(?<=| Average | ..d% | )d %(?=.*)
Комментарии:
1. Похоже, что OP не имеет контроля над итерациями сопоставления, у него есть контроль только над регулярным выражением и группами захвата.
Ответ №2:
Одно из решений, которое я вижу, заключается в том, чтобы иметь регулярное выражение, которое будет захватывать несколько строк, начиная с первого «Среднего» и заканчивая вторым. Что касается наличия всей логики, содержащейся в регулярном выражении, то вам нужно знать, как указать параметры поиска в вашем регулярном выражении, обычно это делается с помощью /sm
. В итоге ваше регулярное выражение будет выглядеть следующим образом:
/^| Average *| d*.d %.*$.*^| Average *| (d*.d %).*$/sm
Захваченная группа содержит только второе вхождение в процентах Average
от Line
.
Ответ №3:
В конце концов, я получил ответ методом проб и ошибок.
| Average | .*d % | *(d*.d%) | d
вычислит столбец под ветвями. Спасибо всем за помощь!
Комментарии:
1. В чем была проблема с моим решением?
2. Во-первых, как указал @cglacet, я искал чистое регулярное выражение. Я взял только регулярное выражение, которое вы упомянули в своем ответе
(?<=| Average *| d % | *)d %(?=.*)
, протестировал его с rubular.com и regex101.com но это не сработало.3. хорошо, я вижу: .NET поддерживает кванторы в поисковых выражениях, в то время как другие реализации регулярных выражений, похоже, их не поддерживают. Хотя это было легко исправить:
(?<=| Average | ..d% | )d %(?=.*)
— смотрите: regex101.com/r/d7TNF9/14. О, теперь я понимаю. Большое спасибо! ^_^
5. np, было забавно создавать эти регулярные выражения, и упомянутое ограничение было новым для меня, так что это ценное преимущество! 😉