Ruby Regex для захвата всего между двумя строками (включительно)

Я пытаюсь очистить некоторый HTML и просто удалить один тег (и мне бы очень хотелось избежать использования nokogiri и т. д.). Итак, у меня появилась следующая строка, от которой я хочу избавиться:

<div class="the_class>Some junk here that's different every time</div>

Это появляется ровно один раз в моей строке, и я хотел бы найти способ его удалить. Я пытался придумать регулярное выражение, чтобы захватить все это, но не могу найти работающее.

Я попробовал /<div class="the_class">(.*)<\/div>/m, и это работает, но он также будет соответствовать любым дополнительным тегам </div> в документе, которые мне не нужны.

Любые идеи о том, как подойти к этому?


person jbrennan    schedule 19.11.2012    source источник
comment
Зачем избегать использования синтаксического анализатора, такого как Nokogiri, если он упрощает то, что вы хотите сделать?   -  person the Tin Man    schedule 19.11.2012
comment
@theTinMan Потому что это добавляет еще одну зависимость и замедляет мою работу. Делает вещи более сложными. Кроме того, это решение применимо не только к тегам HTML. Мои начальные и конечные строки могут быть любыми.   -  person jbrennan    schedule 20.11.2012


Ответы (2)


Я считаю, что вы ищете нежадное регулярное выражение, например:

/<div class="the_class">(.*?)<\/div>/m

Обратите внимание на добавленный ?. Теперь группа захвата будет захватывать как можно меньше (не жадная), а не как можно больше (жадная).

person nickb    schedule 19.11.2012

Потому что это добавляет еще одну зависимость и замедляет мою работу. Делает вещи более сложными. Кроме того, это решение применимо не только к тегам HTML. Мои начальные и конечные строки могут быть любыми.

Раньше я думал так же, пока не получил работу по написанию поисковых роботов и аналитики веб-сайтов, а затем написал большую систему агрегации RSS — парсер был единственным выходом из этого безумия. Без него работа никогда не была бы закончена.

Да, регулярные выражения хороши и полезны, но вас ждут драконы. Например, эта общая строка вызовет проблемы:

'<div class="the_class"><div class="inner_div">foo</div></div>'

Регулярное выражение /<div class="the_class">(.*?)<\/div>/m вернет:

"<div class=\"the_class\"><div class=\"inner_div\">foo</div>"

Этот искаженный, но отображаемый HTML:

<div class="the_class"><div class="inner_div">foo

еще хуже:

'<div class="the_class"><div class="inner_div">foo'[/<div class="the_class">(.*?)<\/div>/m]
=> nil

Принимая во внимание, что парсер может иметь дело с обоими:

require 'nokogiri'
[
  '<div class="the_class"><div class="inner_div">foo</div></div>',
  '<div class="the_class"><div class="inner_div">foo'
].each do |html|
  doc = Nokogiri.HTML(html)
  puts doc.at('div.the_class').text
end

Выходы:

foo
foo

Да, ваши начальные и конечные строки могут быть любыми, но есть общепризнанные инструменты для анализа HTML/XML, и по мере роста вашей задачи недостатки использования регулярных выражений станут более очевидными.

И да, синтаксический анализатор может дать сбой. Мне приходилось обрабатывать RSS-каналы, которые были настолько искажены, что синтаксический анализатор взорвался, но небольшая предварительная обработка решила проблему.

person the Tin Man    schedule 20.11.2012