Получить второе вхождение из второй строки

#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 / но информация о совпадении, которую оно показывает, следующая:

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/1

4. О, теперь я понимаю. Большое спасибо! ^_^

5. np, было забавно создавать эти регулярные выражения, и упомянутое ограничение было новым для меня, так что это ценное преимущество! 😉