正则表达式在1搜索中匹配正则表达式匹配?其他小的正则表达式问题

时间:2014-06-18 03:18:13

标签: ruby regex

我有一封电子邮件,其中包含一些html代码,我正在寻找正则表达式。我正在使用gmail gem来阅读我的电子邮件,并且在阅读gmail时使用nokogiri失败。因此,我正在寻找一个正则表达式解决方案

我想要做的是扫描标有important title的部分,然后查看该部分中的无序列表,捕获网址。下面提供了标有important title的html代码。

我不知道该如何做到这一点,所以我认为正确的方法是,对于名为important title的部分进行正则表达式并将所有内容捕获到无序列表的末尾。然后在这场比赛中,随后找到链接。

为了找到这些链接,我使用了这个正常的正则表达式:(?:")([^"]*)(?:" )

要捕获名为important title的部分,我想简单地使用以下正则表达式(?:important title).*(?:<\/ul>)。根据我的理解,会查找important title,然后查找尽可能多的字符,然后是</ul>。但是从下面来看,它只捕获</h3>。新行字符导致它停止。这是我的一个问题:为什么.应该捕获所有字符,而不是捕获新的行字符?如果这是设计的话,我不需要简单的“它的设计”......

所以假设它是设计的,我接着尝试了(?: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>

2 个答案:

答案 0 :(得分:1)

  

我有html,我正在寻找正则表达式。

使用nokogiri gem:http://nokogiri.org/

它是搜索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 :(得分: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) < em>(不是字符串的开头)禁止这种情况,只允许第一次与第二个入口点匹配。

为了更具可读性,所有模式都使用扩展模式(或详细模式,注释模式或自由间隔模式......),允许在模式内部注释以及忽略空格。可以使用(?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标签),模式失败。为了再次成功,正则表达式引擎将找到一个新的第二个入口点。