Регулярное выражение совпадения с регулярным выражением в 1 поиске? Другие незначительные вопросы о регулярных выражениях

#ruby #regex

#ruby #регулярное выражение

Вопрос:

У меня есть электронное письмо с некоторым HTML-кодом, который я ищу для регулярного выражения. Я использую gmail gem для чтения своих электронных писем и использую nokogiri сбой при чтении через gmail. Таким образом, я ищу решение для регулярных выражений

Что я хотел бы сделать, так это отсканировать раздел, который помечен important title , а затем просмотреть неупорядоченный список в этом разделе, захватив URL-адреса. Помеченный HTML-код important title приведен ниже.

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

Чтобы найти ссылки, я использовал это регулярное выражение, которое отлично работает: (?:")([^"]*)(?:" )

Чтобы захватить раздел, называемый important title however, я хотел просто использовать следующее регулярное (?:important title).*(?:</ul>) выражение. Насколько я понимаю, это будет искать important title как можно больше символов, за которыми следует </ul> . Однако из приведенного ниже он только фиксирует </h3> . Символ новой строки вызывает его остановку. Это один из моих вопросов: почему . which должен захватывать все символы, а не захватывать символ новой строки? Если это сделано специально, мне не нужно больше, чем просто «его дизайн»…

Итак, предполагая, что это сделано специально, я затем попробовал (?:important title)((.|s)*)(?:</ul>) , и по какой-то причине это дало мне 2 совпадения. Первый соответствует всему коду, который мне нужен, останавливаясь на </ul> , а второе совпадение — буквально просто пустая строка. Я не понимаю, почему это так…

Наконец, мой последний и самый важный вопрос: нужно ли мне выполнять 2 регулярных выражения, чтобы получить ссылки? Или есть способ объединить оба регулярных выражения, чтобы мое «регулярное выражение ссылки» выполняло поиск только в моем «регулярном выражении раздела»?

 <h3>the important title </h3>
<ul>
<li><a href="http://www.link.com/23232=
.32434" target="_blank">first link»</a></li>
<li><a href="http://www.link.com/234234468=
.059400" target="_blank">second link »</a></li>
<li><a href="http://www.link.com/287=
.059400" target="_blank">third link»</a></li>
<li><a href="http://www.link.com/4234501=
.059400" target="_blank">fourth link»</a></li>
<li><a href="http://www.link.com/34517=
.059400" target="_blank">5th link»</a></li>
</ul>
  

Ответ №1:

Пример с nokogiri:

 # encoding: utf-8
require 'nokogiri'

html_doc = '''
<h3>the important title </h3>
<ul>
<li><a href="http://www.link.com/23232=.32434" target="_blank">first link»</a></li>
<li><a href="http://www.link.com/234234468=.059400" target="_blank">second link »</a></li>
<li><a href="http://www.link.com/287=.059400" target="_blank">third link»</a></li>
<li><a href="http://www.link.com/4234501=.059400" target="_blank">fourth link»</a></li>
<li><a href="http://www.link.com/34517=.059400" target="_blank">5th link»</a></li>
</ul>
'''

doc = Nokogiri::HTML.parse(html_doc)
doc.search('//h3[text()="the important title "]/following-sibling::ul[1]/li/a/@href').each do |link|
    puts link.content
end
  

Способ регулярного выражения использует привязку, G которая соответствует позиции в конце предыдущего совпадения, поскольку эта привязка инициализируется началом строки в начале, вы должны добавить (?!A) (не начало строки), чтобы запретить этот случай, и разрешить только первое совпадение со второй записьюточка.

Чтобы быть более читабельным, во всех шаблонах используется расширенный режим (или подробный режим, или режим комментариев, или режим свободного пробела …), Который разрешает комментарии внутри шаблона и где пробелы игнорируются. Этот режим можно установить или отменить встроенным с (?x) помощью и (?-x)

 pattern = Regexp.new('
  # entry points
  (?:
      G (?!A)  # contiguous to the precedent match
    |
      <h3> s* (?-x)the important title(?x) s* </h3> s* <ul> s*
  )

  <li>
  <a s  href=" (?<url> [^"]* ) " [^>]* >
  (?<txt> (?> [^<]  | <(?!/a>) )* )
  s* </a> s* </li> s*', Regexp::EXTENDED | Regexp::IGNORECASE)

html_doc.scan(pattern) do |url, txt|
  puts "nurl: #{url}ntxt: #{txt}"
end
  

Первое совпадение использует вторую точку входа: <h3> s* (?-x)the important title(?x) s* </h3> s* <ul> s* и все последующие совпадения используют вторую: G (?!A)
После последнего совпадения, поскольку больше нет смежных тегов li (есть только закрывающий тег ul), шаблон завершается ошибкой. Чтобы снова добиться успеха, механизм регулярных выражений найдет новую вторую точку входа.

Комментарии:

1. извините, я должен был быть более ясным… Я использую драгоценный камень gmail для чтения своих электронных писем, и использование nokogiri не удается при чтении через gmail. Таким образом, я ищу решение для регулярных выражений

Ответ №2:

У меня есть html, который я ищу для регулярного выражения.

Используйте драгоценный камень nokogiri: http://nokogiri.org /

Это стандарт defacto для поиска html. Игнорируйте перечисленные требования — они устарели.

 require 'nokogiri'
require 'open-uri'

#doc = Nokogiri::HTML(open('http://www.some_site.com'))

html_doc = Nokogiri::HTML(<<'END_OF_HTML')
<h3>not important</h3>
<ul>
<li><a href="blah" target="_blank">first link»</a></li>
<li><a href="blech" target="_blank">second link »</a></li>
</ul>

<h3>the important title </h3>
<ul>
<li><a href="http://www.link.com/23232=.32434" target="_blank">first link</a></li>
<li><a href="http://www.link.com/234234468=.059400" target="_blank">second link</a></li>
<li><a href="http://www.link.com/287=.059400" target="_blank">third link</a></li>
<li><a href="http://www.link.com/4234501=.059400" target="_blank">fourth link</a></li>
<li><a href="http://www.link.com/34517=.059400" target="_blank">5th link</a></li>
</ul>
END_OF_HTML

a_tags = html_doc.xpath(
  '//h3[text()="the important title "]/following-sibling::ul[1]//a'
)

a_tags.each do |tag|
  puts tag.content
  puts tag['href']
end

--output:--
first link
http://www.link.com/23232=.32434
second link
http://www.link.com/234234468=.059400
third link
http://www.link.com/287=.059400
fourth link
http://www.link.com/4234501=.059400
5th link
http://www.link.com/34517=.059400
  

Комментарии:

1. извините, я должен был быть более ясным… Я использую драгоценный камень gmail для чтения своих электронных писем, и использование nokogiri не удается при чтении через gmail. Таким образом, я ищу решение для регулярных выражений

2. @Chowza, если вы можете загрузить опубликованный вами HTML-код, вы можете прочитать его с помощью nokogiri. Смотрите Пример, который я опубликовал.

3. @Chowza, Thus I'm looking for a regex solution . Хм, регулярное выражение выполняет поиск в строке, nokogiri также выполняет поиск в строке. Как получилось, что ваша строка непроницаема для поиска nokogiri, но регулярное выражение может свободно искать строку?

4. эй, спасибо за ваш ответ, похоже, что из-за того, что мой файл представлял собой электронное письмо с html, nokogiri не смог его проанализировать (из-за некоторой кодировки base 64 в верхней части письма. В итоге я выполнил регулярное выражение раздела, который был html, а затем смог использовать nokogiri