我有一个这样的字符串:
"Energia Elétrica kWh<span class=\"_ _3\"> </span> 10.942 <span class=\"_ _4\"> </span> 0,74999294 <span class=\"_ _5\"> </span> 8.206,39"
我希望通过HTML标记将其拆分,这些标记始终为<span>
。我试过像:
my_string.split(/<span(.*)span>/)
但它没有用,它只能正确匹配第一个元素。
有谁知道我的正则表达式有什么问题?在这个例子中,我期望返回值为:
["Energia Elétrica kWh", "10.942", "0,74999294" ,"8.206,39"]
我想要像strip_tags
这样的东西,但不是返回已清理过的字符串,而是通过删除标签来拆分数组。
答案 0 :(得分:2)
不要使用模式来操纵HTML。这是一个path destined to make you insane。
而是使用HTML解析器。 Ruby的标准是Nokogiri:
require 'nokogiri'
doc = Nokogiri::HTML::DocumentFragment.parse("Energia Elétrica kWh<span class=\"_ _3\"> </span> 10.942 <span class=\"_ _4\"> </span> 0,74999294 <span class=\"_ _5\"> </span> 8.206,39")
您可以使用text
来提取所有文本,但是,如果它是您正在使用的结构化数据,那么通常会很难提取字段,因为文本节点可以连接在一起,从而产生连续的单词,所以要小心:
doc.text # => "Energia Elétrica kWh 10.942 0,74999294 8.206,39"
相反,我们通常从各个节点提取数据:
doc.search('span')[1].next_sibling.text # => " 0,74999294 "
doc.search('span').last.next_sibling.text # => " 8.206,39"
或者,我们遍历节点,然后使用map
来获取节点的文本:
doc.search('span').map{ |span| span.next_sibling.text.strip }
# => ["10.942", "0,74999294", "8.206,39"]
我会解决这个问题:
data = [doc.at('span').previous_sibling.text.strip] # => ["Energia Elétrica kWh"]
data += doc.search('span').map{ |span| span.next_sibling.text.strip }
# => ["Energia Elétrica kWh", "10.942", "0,74999294", "8.206,39"]
或者:
spans = doc.search('span')
data = [
spans.first.previous_sibling.text,
*spans.map{ |span| span.next_sibling.text }
].map(&:strip)
# => ["Energia Elétrica kWh", "10.942", "0,74999294", "8.206,39"]
虽然正则表达式通常可以用于初始尝试,但HTML格式的更改可能会破坏模式,强制进行其他更改,然后进行另一次更改,然后再进行另一次更改,直到模式过于复杂,而正确编写的解析器方法通常会非常有弹性并且对问题免疫。
答案 1 :(得分:1)
如果你真的需要使用正则表达式来做到这一点,你几乎已经拥有它了。
irb(main):010:0> string.split(/<span.+?span>/)
=> ["Energia Eltrica kWh", " 10.942 ", " 0,74999294 ", " 8.206,39"]
您只需要?
告诉它尽可能少地匹配。