Qt / QRegularExpression — не удается зафиксировать все результаты, только 1-й экземпляр, почему?

Я пытаюсь получить текст, окруженный тегами <td>. Моя проблема в том, что я могу получить только первый результат и не могу получить другие.

Из следующего HTML я получаю только первый результат, который представляет собой этот текст:

Имя ученика

Но все остальные попытки захватить остальную часть нужного текста пусты, нулевые. Почему так и что я делаю не так?

Текст для работы с регулярным выражением:

<table width="52%" border="1" align="center" cellpadding="1" cellspacing="1">
  <tr>
    <td colspan="2" align="center" bgcolor="#999999">Result</td>
    </tr>
  <tr>
    <td width="22%"><strong>Student ID</strong></td>
    <td width="78%">13/0003337/99</td>
  </tr>
  <tr>
    <td><strong>Student Name</strong></td>
    <td>Alaa Salah Yousuf Omer</td>
  </tr>
  <tr>
    <td><strong>College</strong></td>
    <td>Medicine & General Surgery</td>
  </tr>
  <tr>
    <td><strong>Subspecialty</strong></td>
    <td>General</td>
  </tr>
  <tr>
    <td><strong>Semester</strong></td>
    <td>Fourth</td>
  </tr>
  <tr>
    <td><strong>State</strong></td>
    <td>Pass</td>
  </tr>
  <tr>
    <td><strong>Semester's GPA</strong></td>
    <td>2.89</td>
  </tr>
  <tr>
    <td><strong>Overall GPA</strong></td>
    <td>3.13</td>
  </tr>
  </table>

Мой код:

QString resultHTML = "A variable containing the html code written above."

QRegularExpression regex("<td>(.*)</td>", QRegularExpression::MultilineOption);
QRegularExpressionMatch match = regex.match(resultHTML);

// I only get the 1st result logged withing debugger
for(int x = 0; x <= match.capturedLength(); x++)
{
    qDebug() << match.captured(x);
}

// This here doesn't get me anything, null!
_studentName = match.captured(2);
_semesterWritten = match.captured(8);
_stateWritten = match.captured(10);
_currentGPA = match.captured(12);
_overallGPA = match.captured(14);

person Alaa Salah    schedule 21.01.2016    source источник
comment
Пожалуйста, не анализируйте HTML с помощью регулярных выражений!   -  person peppe    schedule 22.01.2016
comment
@peppe Да, конечно, но при работе с небольшими объемами данных я просто предпочитаю, чтобы это было как можно проще.   -  person Alaa Salah    schedule 22.01.2016


Ответы (2)


Вы хотите применить то, что Perl называет глобальным флагом/модификатором регулярного выражения, что означает продолжение поиска совпадений после того, как будет найдено первое.

Чтобы сделать это с помощью QT, попробуйте использовать globalMatch() вместо match().

Первый вернет QRegularExpressionIterator, по которому вы можете выполнить итерацию, чтобы найти все совпадения. .

Кроме того, * в <td>(.*)</td> является жадным, поэтому он найдет первый экземпляр <td>, а затем захватит как как можно больше (включая большую часть вашего контента и дополнительные теги <td>), если в конце можно найти </td>.

Есть разные способы избежать этого. Один из способов — использовать <td>(.*?)</td>, чтобы захватить как можно меньше мало, если в конце можно найти </td>. По сути, это зафиксировало бы все в одном теге <td />, если нет другого тега <td />, вложенного дальше (что не похоже на случай в вашем сценарии). ).

Кроме того, QRegularExpression::MultilineOption PatternOption здесь не нужен, поскольку он относится к символам регулярного выражения ^ и $, которые вы не используете.

Вместо этого вас может заинтересовать параметр PatternOption QRegularExpression::DotMatchesEverythingOption, который включает новые строки в точках на тот случай, если теги <td /> или содержащиеся в них значения охватывают несколько линии

person Jordan Pilat    schedule 21.01.2016

...Глобальное сопоставление полезно для поиска всех вхождений заданного регулярного выражения в строке темы...

QRegularExpressionMatchIterator i = regex.globalMatch(resultHTML);

while (i.hasNext()) 
{
    QRegularExpressionMatch match = i.next();        
    qDebug() << match.captured();
}
person Vladimir Bershov    schedule 21.01.2016