如果可能的话,我建议使用一个库来完成这个任务,因为地址解析很困难。看一下Indirizzo Ruby gem,它可以让这个过程变得简单:
require 'Indirizzo'
address = Indirizzo::Address.new("7707 Foo Bar Blvd")
address.number
=> "7707"
address.street
=> ["foo bar blvd", "foo bar boulevard"]
即使您不使用Indirizzo库本身,阅读其源代码可能非常有用,以了解他们如何解决问题。例如,它具有经过精细调整的正则表达式,以匹配地址的不同部分:
Match = {
# FIXME: shouldn't have to anchor :number and :zip at start/end
:number => /^(\d+\W|[a-z]+)?(\d+)([a-z]?)\b/io,
:street => /(?:\b(?:\d+\w*|[a-z'-]+)\s*)+/io,
:city => /(?:\b[a-z][a-z'-]+\s*)+/io,
:state => State.regexp,
:zip => /\b(\d{5})(?:-(\d{4}))?\b/o,
:at => /\s(at|@|and|&)\s/io,
:po_box => /\b[P|p]*(OST|ost)*\.*\s*[O|o|0]*(ffice|FFICE)*\.*\s*[B|b][O|o|0][X|x]\b/
}
这些文件可以从源代码中提供更详细的信息:
(但我也基本同意@drhenner的评论,为了让自己更容易,您可能只需在单独的字段中接受这些数据输入。)
编辑:为了更具体地回答如何删除街道后缀(例如“Blvd”),您可以使用Indirizzo的正则表达式常量(例如constants.rb
中的Suffix_Type
)进行操作:
address = Indirizzo::Address.new("7707 Foo Bar Blvd", :expand_streets => false)
address.street.map {|street| street.gsub(Indirizzo::Suffix_Type.regexp, '').strip }
=> ["foo bar"]
(请注意,我还向初始化程序传递了
:expand_streets => false
,以避免在丢弃后缀的情况下扩展“Blvd”和“Boulevard”这两个替代项。)