Проблема Boost :: regex, соответствие элементу HTML span - PullRequest
1 голос
/ 12 июля 2009

Я не понимаю. Я создал это регулярное выражение:

<span class="copy[Green|Red].*>[\s]*(.*)[&#92;s]*<\/span>

для соответствия определенным частям HTML-кода (часть между пролетами). Например, следующее:

<span class="copyGreen">0.12</span>
<span class="copyRed">  0.12  </span>

Теперь, это прекрасно работает с RegexBuddy и другими, но с Boost :: regex У меня есть проблема. Это не совпадает.

РЕДАКТИРОВАТЬ: Чтобы быть более точным, я хочу захватить число между промежутками. До и после число, также могут быть пробелы (\ n, \ r и т. д.).

Вот код, который я сделал:


try {
        const boost::regex e("<span class=\"copy[Green|Red].*>[\\s]*(.*)[\\s]*<\\/span>");
        boost::smatch matches;
        std::string html("<span class=&#92;"copyGreen&#92;">  0.12  </span>");

        if (boost::regex_match(html, matches, e)) {
                // Works... (not).
        } else {
                throw std::runtime_error("Couldn't match the regex against HTML-source!");
        }
} catch (boost::regex_error& e) {
        std::cout << e.what() << std::endl;
}

Что я здесь не так делаю? Заранее спасибо!

EDIT:

Кажется, правильное выражение будет

boost::regex("<span class=&#92;"copy(?:Green|Red)[^>]*>\\s*(.*?)\\s*<\\/span>"); // Thanks chaos!.

Это на самом деле совпадает с Boost. Однако мне нужно было включить boost :: match_extra чтобы получить все нужные мне снимки. Это было сделано путем определения

BOOST_REGEX_MATCH_EXTRA

в boost \ regex \ user.hpp

Еще раз спасибо.

Ответы [ 3 ]

2 голосов
/ 12 июля 2009

С одной стороны, это:

[Green|Red]

не делает то, что вы думаете, что делает. Вы хотите:

(?:Green|Red)

[Green|Red] - это класс символов, состоящий из букв GRred|, а не способ чередования совпадений. Как вы и написали, он будет точно соответствовать одному из тех символов, за которыми следует любое количество других символов.

Это:

[\s]

является избыточным и может быть опасным (в зависимости от интерпретации это может быть причиной того, что ваш матч не работает). Это может быть просто

\s

Чтобы ваш второй \s работал, выражение захвата, вероятно, должно быть

(.*?)

Я также рекомендую превратить ваш первый .* в [^>]*, чтобы избежать проблемы, которая возникнет, если вы когда-либо примените это к реальным документам HTML, где он будет поглощать произвольные объемы HTML.

1 голос
/ 12 июля 2009
[Green|Red]

Неправильно, потому что [] обозначает класс символов в большинстве синтаксисов регулярных выражений. Классы символов - это в основном группы символов, которые могут быть сопоставлены. Например, [abc] будет соответствовать «a», «b» или «c».

Что касается других ваших проблем, есть пара возможностей, таких как упоминание TokenMacGuy; (. *) может слишком много совпадать. Чтобы быть уверенным, мне нужно посмотреть, что именно соответствует вашему регулярному выражению.

Наконец, вам действительно не следует использовать регулярные выражения для разбора HTML. Он попадает в точку, где он просто не работает, кроме как в самых контролируемых условиях и со сложными выражениями. Было бы лучше изучить различные парсеры html / xml.

Редактировать: Это является отличным объяснением того, почему это плохая идея.

1 голос
/ 12 июля 2009

Есть пара проблем с вашим регулярным выражением.

Первый бит: [Green|Red]

, который соответствует набору символов, этот набор равен G, r, e, n, |, R и d.

вам нужно сделать это, используя скобки, например (Green|Red). теперь это соответствует либо строке Green, либо Red.

РЕДАКТИРОВАТЬ: если вы не хотите, чтобы это захватывало что-либо, вы можете использовать группу без захвата, что в boost :: regex выполняется путем включения ?: после первой круглой скобки: (?:Green|Red). Теперь регулярное выражение имеет группирующее поведение круглых скобок, но нет захвата.

Вторая проблема (.*)

Это не так уж много, но слишком много, включая шаблоны, такие как последовательные пролеты. Это будет использовать конец одного промежутка и начало следующего, вплоть до последнего промежутка на странице. Вы должны сделать это не жадным. В boost :: regex вы делаете это, следуя * с ?. измените его на (.*?) (и сделайте то же самое с другими *.

Дело в том, что XML и HTML очень сложно заставить работать что-то большее, чем просто простые регулярные выражения. Вы действительно должны использовать библиотеку, которая предназначена для работы с этим форматом. Существует множество вариантов . Таким образом, вы можете быть уверены, что обрабатываете HTML правильно, независимо от того, насколько искаженным может быть ввод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...