Here's my own submission for this problem. Once you wrap your head
around a few bits of the regular expression, it's pretty simple to
understand.
class Rule
attr_reader :fields
def initialize(str)
patt = str.gsub(/\[(.+?)\]/, '(?:\1)?').gsub(/<(.+?)>/, '(.+?)')
@pattern = Regexp.new('^' + patt + '$')
@fields = nil
end
def match(str)
if md = @pattern.match(str)
@fields = md.captures
else
@fields = nil
end
end
end
rules = []
File.open(ARGV[0]).each do |line|
line.strip!
next if line.empty?
rules << Rule.new(line)
end
unknown = []
File.open(ARGV[1]).each do |line|
line.strip!
if line.empty?
puts
next
end
if rule = rules.find { |rule| rule.match(line) }
indx, data = rules.index(rule), rule.fields.reject { |f| f.nil? }
puts "Rule #{indx}: #{data.join(', ')}"
else
unknown << line
puts "# No match"
end
end
puts "\nUnmatched input:"
puts unknown.join("\n")