Объединение регулярных выражений для извлечения данных в C#

#c# #regex #tuples

#c# #регулярное выражение #кортежи

Вопрос:

У меня есть строка, содержащая HTML, которая жестко запрограммирована в следующем формате:

 <span class="Marker" id="a">Some text 1</span><br>
<span class="Marker" id="b">Some text 2</span><br>
<span class="Marker" id="c">Some text 2</span><br>
<p class="inactive">Some text 4</p>
<p class="inactive">Some text 5</p>
  

Моя цель — перебирать каждую строку и:

  1. Извлеките текст.
  2. Проверьте, содержит ли строка class=»Marker»

Сохраните эту информацию в списке.

Я хочу сначала извлечь только текст из HTML и сохранить их в списке, поэтому у меня есть следующее:

 //(?<=>)  -> Lookbehind
//(?=<)   -> Lookahead
var matches = Regex.Matches(htmlString, "(?<=>)([^<] )(?=<)");
List<string> list = new List<string>();

foreach (Match match in matches)
{
   list.Add(match.Value);
}
  

Это работает, как и ожидалось. Теперь я хочу определить, содержит ли каждая строка строку class=»Marker», поэтому у меня есть следующее:

 var classes = Regex.Matches(html, "(?<=<span class=")([A-Za-z] )(?=")");
List<bool> isPresentList = new List<bool>();
foreach (Match cl in classes)
{
    bool isPresent = cl.ToString().Equals("Marker", StringComparison.Ordinal);
    isPresentList.Add(isPresent);
}
  

Это также работает, как и ожидалось, но я хочу иметь возможность сделать это всего за один шаг, если это возможно.

Есть ли способ объединить фильтры регулярных выражений вместе, чтобы мне возвращался текст и если маркер есть или нет (например, в кортеже)?

Комментарии:

1. Регулярные выражения — очень плохой инструмент для обработки XML / HTML. Почему бы не использовать один, разработанный специально для этого? Например. htmlagilitypack.codeplex.com

2. Это делает мою работу, поскольку HTML не изменится по сравнению с этим форматом.

Ответ №1:

Как насчет регулярного выражения, подобного приведенному ниже?

     <([w]*) class="(w*)"[ =w"]*>([ w]*)</1>
  

который включает обратную ссылку 1 на группу, которая фиксирует имя тега ([w]*) . Маркер (имя класса) также записывается с class="(w*)" помощью .

Если ваш текст внутри тегов html, вероятно, содержит знаки препинания, вы могли бы захотеть изменить [ w] раздел на что-то другое, например (.*?) , захватить любые символы, используя отложенный квантификатор.

См.: https://regex101.com/r/Ufluqs/2 для примера используйте предоставленные вами данные.

Предупреждение: у вас могут возникнуть проблемы с использованием подхода регулярных выражений по ряду причин, например, если html-атрибуты записаны в другом порядке или вложены html-теги.

Комментарии:

1. Я обновил регулярное выражение для вас, я думаю, оно ближе к тому, что вы хотели.

2. Ваше решение отлично работает по веб-ссылке, но когда я использую его в C # следующим образом, var соответствует = регулярному выражению. Совпадения(html, «<([\w]*) class=»(\w*)»[ =\w»]*>((.*?)*)<\/\1>»); возвращаемое строковое значение равноисходная строка, например, » <span>Некоторый текст 2<br>».< /span> Есть ли способ, которым он может возвращать отдельные групп ы? т.е «Маркер» и «Некоторый текст 2»?

3. Попробуйте найти совпадение. Свойство групп для повторного поиска отдельных групп.

4. Быстрый вопрос, я изменил последнюю группу на ((.*?)*), поскольку моя строка может содержать знаки препинания. Зачем нужны два набора круглых скобок? Если внутреннее регулярное выражение означает «любой символ ноль или более раз», тогда зачем нужен дополнительный * после него?

5. Я думаю, вы правы, и вам не нужен дополнительный набор круглых скобок.