sregex_iterator не находит соответствий на строке

158
28 июля 2019, 09:50

У меня есть строка - html код, который нужно распарсить с помощью регулярных выражений regex. Мне нужно записать в вектор std::vector все URL'ы на странице, находящиеся в href="". Мой C++ код регулярных не работает.

#include <regex>
#include <iostream>
#include <string>
using std::string;
using std::regex;
using std::cout;
using std::endl;
using std::sregex_iterator;
using std::smatch;
int main()
{
    string subject("<head><title>Search engines</title></head><body><a href=\"https://yandex.ru\">Yandex</a><a href=\"https://google.com\"></a></body>");
    try {
        regex re("<\\s*A\\s+[^>]*href\\s*=\\s*\"([^\"]*)\"");
        sregex_iterator next(subject.begin(), subject.end(), re);
        sregex_iterator end;
        if (next == end)
            cout << "Oops" << endl;
        while (next != end) {
            smatch match = *next;
            cout << match.str() << endl;
            next++;
        }
    } catch (std::regex_error& e) {
        ; // Syntax error in the regular expression
    }
    return 0;
}

Только Python'овский работает.

#!/usr/bin/python3
import re
html = '<head><title>Search engines</title></head><body><a href="https://yandex.ru">Yandex</a><a href="https:/google.com"></a></body>'
title = re.findall(r'<title>(.*?)</title>', html)[0]
links = [ x[1] for x in re.findall(r'<a\s+(?:[^>]*?\s+)?href=(["\'])(.*?)\1', html)]
print (title)
print (links)

Догадываюсь что можно просидеть неделю, листая справочник Джеффри Фридла по регулярным выражениям и библиотеке regex, и добиться нужного результата, но stackoverflow предназначен не для советов типа "читай Фридла, а не проси переварить кашу". К тому же на такой, казалось бы полезный вопрос, нет ответа на стэке, чтоб работало.

Answer 1

Исправить код можно с помощью флага std::regex_constants::icase, а также использовании sregex_token_iterator с 1 в качестве четвёртого аргумента (для получения значения в захватывающей подмаске №1). В Python re.findall возваращает только захваченные подстроки, если в шаблоне указаны захватывающие подмаски, в C++ нет такого метода.

Пример работающего кода на C++:

#include <iostream>
#include <string>
#include <vector>
#include <regex>
using namespace std;
int main() {
    regex re("<\\s*A\\s+(?:[^>]*?\\s+)?href\\s*=\\s*\"([^\"]*)\"", std::regex_constants::icase);
    string subject("<head><title>Search engines</title></head><body><a href=\"https://yandex.ru\">Yandex</a><a href=\"https://google.com\"></a></body>");
    vector<string> result(sregex_token_iterator(subject.begin(), subject.end(), re, 1),
                               sregex_token_iterator());
    for( auto & s : result ) cout << s << endl;
    return 0;
}
// => https://yandex.ru, https://google.com
READ ALSO
extern Template from function in Class

extern Template from function in Class

Пробую унести из декларации класса Template в реализацию, все попытки приводят к ругани компилятора, не совсем понимаю как работает в этом случае...

145
Обнуление массива в Си

Обнуление массива в Си

Как правильно обнулить массив? Речь о любых типах массива, будь то символьный, целочисленный, динамический и тп Если способов несколько то желательно...

204