C ++ Регулярные выражения * сохранение только последнего совпадающего [дубликата]

Я столкнулся с этим и попробовал все другие решения. У меня не было файла .class в моей папке HTML, у меня был только файл .java. Когда я добавил файл .class, программа работала нормально.

8
задан Piotr Skotnicki 24 September 2015 в 15:46
поделиться

3 ответа

Вы получаете 1, потому что regex_search возвращает только 1 совпадение, а size() возвращает количество групп захвата + все значение соответствия.

Ваш matches is ...:

Объект типа match_results (например, cmatch или smatch), который заполняется этой функцией, с информацией о результатах совпадения и любой найдены подматрицы.

Если [поиск по регулярному выражению] успешный, он не пуст и содержит ряд объектов sub_match: первый элемент sub_match соответствует всему совпадению, если выражение регулярного выражения содержало подвыражения, которые должны быть сопоставлены (т. е. группы с разделителями в скобках), их соответствующие подрежимы сохраняются как последовательные элементы sub_match в объекте match_results.

код, который найдет несколько совпадений:

#include <string>
#include <iostream>
#include <regex>
using namespace std;
int main() {
  string str("abcdefabcghiabc");
  int i = 0;
  regex rgx1("abc");
  smatch smtch;
  while (regex_search(str, smtch, rgx1)) {
        std::cout << i << ": " << smtch[0] << std::endl;
        i += 1;
        str = smtch.suffix().str();
  }
  return 0;
}

См. IDEONE demo , возвращающий abc 3 раза.

Поскольку этот метод уничтожает входную строку, здесь другая альтернатива, основанная на std::sregex_iterator (std::wsregex_iterator, должна использоваться, когда y наш объект является объектом std::wstring):

int main() {
    std::regex r("ab(c)");
    std::string s = "abcdefabcghiabc";
    for(std::sregex_iterator i = std::sregex_iterator(s.begin(), s.end(), r);
                             i != std::sregex_iterator();
                             ++i)
    {
        std::smatch m = *i;
        std::cout << "Match value: " << m.str() << " at Position " << m.position() << '\n';
        std::cout << "    Capture: " << m[1].str() << " at Position " << m.position(1) << '\n';
    }
    return 0;
}

См. демонстрацию IDEONE , возвращая

Match value: abc at Position 0
    Capture: c at Position 2
Match value: abc at Position 6
    Capture: c at Position 8
Match value: abc at Position 12
    Capture: c at Position 14
9
ответ дан Wiktor Stribiżew 19 August 2018 в 01:16
поделиться
  • 1
    Примечание: приведенный выше пример будет clobber str, поэтому сделайте копию, если вам нужно ее сохранить. Важным битом является получение smatch.suffix().str(), который возвращает текст после совпадения. Цикл while повторяет совпадение оставшейся строки до тех пор, пока не будет найдено больше совпадений. – Mr. Llama 24 September 2015 в 15:48
  • 2
    Да, верно, чтобы сохранить str, просто используйте его копию. – Wiktor Stribiżew 24 September 2015 в 15:50
  • 3
    @ Morpheu5, если что-то еще не ясно, сообщите мне. – Wiktor Stribiżew 24 September 2015 в 21:20
  • 4
    Очень ясно, благодарю. – Morpheu5 25 September 2015 в 08:04
  • 5
    Я обновил ответ другим std::sregex_iterator методом получения всех (вспомогательных) совпадений с их позициями внутри входной строки. – Wiktor Stribiżew 26 November 2015 в 16:21
Решение

@ stribizhev имеет квадратичную сложность худшего случая для правильных регулярных выражений. Для безумных (например, «y *») он не заканчивается. В некоторых приложениях эти проблемы могут быть вызваны DoS-атаками . Вот фиксированная версия:

string str("abcdefabcghiabc");
int i = 0;
regex rgx1("abc");
smatch smtch;
auto beg = str.cbegin();
while (regex_search(beg, str.cend(), smtch, rgx1)) {
    std::cout << i << ": " << smtch[0] << std::endl;
    i += 1;
    if ( smtch.length(0) > 0 )
        std::advance(beg, smtch.length(0));
    else if ( beg != str.cend() )
        ++beg;
    else
        break;
}

Согласно моим личным предпочтениям, это найдет n + 1 совпадений пустого регулярного выражения в строке длины n. Вы также можете просто выйти из цикла после пустого совпадения.

Если вы хотите сравнить производительность для строки с миллионами совпадений, добавьте следующие строки после определения str (и не забудьте включить оптимизацию), один раз для каждой версии:

for (int j = 0; j < 20; ++j)
    str = str + str;
0
ответ дан Arne Vogel 19 August 2018 в 01:16
поделиться

Что вам не хватает, так это то, что matches заполняется одной записью для каждой группы захвата (включая всю согласованную подстроку как 0-й захват).

Если вы пишете

std::regex needle("a(b)c");
]

, то вы получите matches.size()==2, с matches[0]=="abc" и matches[1]=="b".

3
ответ дан Toby Speight 19 August 2018 в 01:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: