【问题标题】:Regex parse using Nokogiri使用 Nokogiri 进行正则表达式解析
【发布时间】:2011-03-17 09:43:40
【问题描述】:

使用 Nokogiri,我需要解析给定的块:

<div class="some_class">
  12 AB / 4+ CD
  <br/>
  2,600 Dollars
  <br/> 
</div>

如果存在abcddollars 值,我需要获取它们。

ab = p.css(".some_class").text[....some regex....]
cd = p.css(".some_class").text[....some regex....]
dollars = p.css(".some_class").text[....some regex....]

正确吗?如果是这样,有人可以用正则表达式帮助我解析 abcddollars 值吗?

【问题讨论】:

    标签: ruby regex nokogiri


    【解决方案1】:

    要获得更好的答案,您必须明确说明 AB、CD 和 Dollar 值采用什么格式,但这里是基于给出的示例的解决方案。它使用正则表达式分组() 来捕获我们感兴趣的信息。(有关详细信息,请参阅答案底部)

    text = p.css(".some_class").text
    
    # one or more digits followed by a space followed by AB, capture the digits
    ab = text.match(/(\d+) AB/).captures[0] # => "12"
    
    # one of more non digits followed by a literal + followed by CD
    cd = text.match(/(\d+\+) CD/).captures[0] # => "4+"
    
    # digits or commas followed by "Dollars"
    dollars = text.match(/([\d,]+) Dollars/).captures[0] # => "2,600"
    

    请注意,如果不匹配,则String#match 返回nil,因此如果值可能不存在,则需要进行检查,例如

    if match = text.match(/([\d,]+) Dollars/)
      dollars = match.captures[0]
    end
    

    捕获的附加说明

    为了匹配 AB 的数量,我们需要一个模式 /\d+ AB/ 来识别文本的正确部分。然而,我们真的只对数字部分感兴趣,所以我们用括号括起来,以便我们可以提取它。例如

    irb(main):027:0> match = text.match(/(\d+) AB/)
    => #<MatchData:0x2ca3440>           # the match method returns MatchData if there is a match, nil if not
    irb(main):028:0> match.to_s         # match.to_s gives us the entire text that matched the pattern
    => "12 AB"
    irb(main):029:0> match.captures     
    => ["12"]
    # match.captures gives us an array of the parts of the pattern that were enclosed in ()
    # in our example there is just 1 but there could be multiple
    irb(main):030:0> match.captures[0]
    => "12"                             # the first capture - the bit we want
    

    查看MatchData 的文档,尤其是captures 方法以了解更多详细信息。

    【讨论】:

    • 注意:如果没有匹配,那么这不是你的变量,例如dollars 将是 nil 这就是问题所在 - 它会导致尝试在 nil 上调用 captures 方法会失败,这就是您可能需要检查的原因。
    • 啊。好的,我明白了。那么捕获方法是什么?因为现在它可以正常工作而无需捕获。
    • 我在答案中添加了更多关于捕获的解释。我希望这会有所帮助。
    【解决方案2】:

    这是一个较旧的线程,但我偶然发现了它。以下是我如何定位值和存储值的可用方式:

    require "ap"
    require "nokogiri"
    
    xml = <<EOT
    <div class="some_class">
      12 AB / 4+ CD
      <br/>
      2,600 Dollars
      <br/> 
    </div>
    EOT
    
    doc = Nokogiri::XML(xml)
    
    some_class = doc.at('.some_class').text
    
    values = some_class
      .scan(/([\d+]+) ([a-z,]+)/i)
      .each_with_object({}){ |(v,c), h| h[c] = v.to_i }
    
    values # => {"AB"=>12, "CD"=>4, "Dollars"=>600}
    

    【讨论】:

    • 有没有办法让 nokogiri 只返回与某个正则表达式模式匹配的数据,而不是返回所有内容,然后再将逻辑应用于它? esp,当解析一个大的 xml 文件时,也许让 nokogiri 返回我们想要的位会更快?或者稍后过滤它会更快?谢谢。
    • XPath2 支持正则表达式,而较旧的 XPath1 不支持。 Nokogiri 的 CSS 提供了一些不允许正则表达式但可以提供帮助的 jQuery 类型的扩展。让 libXML2 库进行提升/搜索比将每个节点返回给 Nokogiri 然后筛选它们要快,但您可以使用基准测试证明这一点。
    猜你喜欢
    • 1970-01-01
    • 2013-05-11
    • 2015-05-16
    • 2015-09-06
    • 2013-09-24
    • 2012-07-08
    • 2020-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多