【问题标题】:File IO read by delimeter?分隔符读取的文件 IO?
【发布时间】:2013-12-11 00:54:35
【问题描述】:

我有以下脚本,它读取一个文件,然后根据以</h1> 结尾的行将其放入一个数组中。如何只读取<h1></h1> 之间的内容?

这是我的脚本:

out_array = []
open('foo.html') do |f|
  f.each('</h1>') do |record|
    record.gsub!("\n", ' ')
    out_array.push record
  end
end

# print array
p out_array

这是我的html

</h1>
akwotdfg
<h1>
<h1>I am foo</h1>
<h1>
    Stubborn quaz
</h1>
<h3>
    iThis
    is a reas
    long one line shit
</h3>
<h1>I am foo</h1>

这是我的输出:

["</h1>", " akwotdfg <h1> <h1>I am foo</h1>", " <h1>     Stubborn quaz </h1>", " <h3>     iThis      is a reas     long one line shit </h3> <h1>I am foo</h1>", " "]

【问题讨论】:

  • 这个程序是基于行的,而 HTML 本身是基于标签的。不是说不可能,但是用手工制作的正则表达式解析 HTML 是很痛苦的。

标签: ruby file-io io


【解决方案1】:

请看下面的代码:

out_array = open('foo.html') do |f|
  f.read.scan(/<h1>(.*)<\/h1>/)
end

puts out_array

执行结果:

I am foo
I am foo

更新为多行扫描:

out_array = open('tempdir/foo.html') do |f|
  f.read.scan(/<h1>([^<]*?)<\/h1>/m) 
end
out_array.map! {|e| e[0].strip}

p out_array

执行结果:

["I am foo", "Stubborn quaz", "I am foo"]

【讨论】:

  • 看起来不错,但是当你有多行 h1 标签时它会中断
  • 多行可以试试"f.read.scan(/

    ([^/m)"

【解决方案2】:

不要使用正则表达式来处理 HTML 或 XML。对于您管理的琐碎内容是可能的,但您的代码可能会因其他人的出价而更改的任何内容而损坏。

改为使用解析器,例如Nokogiri:

require 'nokogiri'

html = '
</h1>
akwotdfg
<h1>
<h1>I am foo</h1>
<h1>
    Stubborn quaz
</h1>
<h3>
    iThis
    is a reas
    long one line
</h3>
<h1>I am foo</h1>
'

doc = Nokogiri::HTML(html)
h1_contents = doc.search('h1').map(&:text)
puts h1_contents

哪些输出:

# >> 
# >>     I am foo
# >>     
# >>         Stubborn quaz
# >>     
# >>     
# >>         iThis
# >>         is a reas
# >>         long one line
# >>     
# >>     I am foo
# >> I am foo
# >> 
# >>         Stubborn quaz
# >>     
# >> I am foo

请注意,Nokogiri 正在返回 &lt;h3&gt; 块内的内容。这是正确/预期的行为,因为 HTML 格式错误。 Nokogiri 修复了格式错误的 HTML 以帮助检索可用内容,但由于结束标记有许多可能的位置,所以 Nokogiri 将结束标记插入到语法正确的最后一个位置。人类早知道这样做,但这是试图提供帮助的软件。

这种情况需要您预处理 HTML 以使其正确。我正在使用一个简单的sub 来修复找到的第一个&lt;h1&gt;

doc = Nokogiri::HTML(html.sub(/^(<h1>)$/, '\1</h1>'))
h1_contents = doc.search('h1').map(&:text)
puts h1_contents
# >> I am foo
# >> 
# >>     Stubborn quaz
# >> I am foo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-07
    • 2010-09-21
    • 1970-01-01
    • 1970-01-01
    • 2020-11-21
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    相关资源
    最近更新 更多