我正在解析文本文件,并希望能够扩展可以轻松识别的令牌集。目前我有以下内容:
if line =~ /!DOCTYPE/
puts "token doctype " + line[0,20]
@ast[:doctype] << line
elsif line =~ /<html/
puts "token main HTML start " + line[0,20]
html_scanner_off = false
elsif line =~ /<head/ and not html_scanner_off
puts "token HTML header starts " + line[0,20]
html_header_scanner_on = true
elsif line =~ /<title/
puts "token HTML title " + line[0,20]
@ast[:HTML_header_title] << line
end
有没有办法用yield块写这个,例如类似的东西:
scanLine("title", :HTML_header_title, line)
答案 0 :(得分:2)
如果您打算解析HTML内容,您可能希望使用其中一种非常高质量的HTML解析器,如nokogiri(http://nokogiri.org/)或Hpricot(http://hpricot.com/)。一个自己动手的方法可能需要更长的时间来完善,而不是弄清楚如何使用其中一个解析器。
另一方面,如果你正在处理的东西不是HTML,并且无法以这种方式解析,那么你需要以某种方式推销自己的东西。有一些Ruby解析器框架可能会有所帮助,但对于性能不是关键因素的简单任务,你可以像在这里一样使用一堆正则表达式。
答案 1 :(得分:2)
Don't parse HTML with regexes.
除此之外,有几种方法可以做你正在谈论的事情。之一:
class Parser
class Token
attr_reader :name, :pattern, :block
def initialize(name, pattern, block)
@name = name
@pattern = pattern
@block = block
end
def process(line)
@block.call(self, line)
end
end
def initialize
@tokens = []
end
def scanLine(line)
@tokens.find {|t| line =~ t.pattern}.process(line)
end
def addToken(name, pattern, &block)
@tokens << Token.new(name, pattern, block)
end
end
p = Parser.new
p.addToken("title", /<title/) {|token, line| puts "token #{token.name}: #{line}"}
p.scanLine('<title>This is the title</title>')
这有一些限制(比如不检查重复的令牌),但有效:
$ ruby parser.rb
标题标题:&lt; title&gt;这是标题&lt; / title&gt;
$