【问题标题】:RegEx Address Parsing CityRegEx地址解析城市
【发布时间】:2013-06-28 23:36:13
【问题描述】:

在我们的数据库中,我们有 1 个“地址”字段,将完整地址存储为文本。我正在将地址拆分为以下字段:Line1、City、State、Zip。 (美国地址)。我在解析 state 和 zip 方面有很好的表达方式,但我在解析 city 时遇到了一些困难。

基本上,我使用以下规则来解析城市:

  • 它必须出现在状态之前
  • 它前面可以有一个逗号,也可以有两个或多个空格。
  • 如果以上都不成立,则只返回状态之前的 1 个单词。

我对验证这些地址不感兴趣。

这是我一直在使用的 RegEx 示例,它非常适合解析由逗号或超过 2 个空格分隔的地址组件,但如果我尝试包含前 1 个词的替代词:

示例地址:1977 S. Joshua Tree PL, Palm Springs, CA 92264

.*(?i)(?((((,\s|\s{2,})\w+)+(\s\w+)))(?=(,\s+|\s+)(阿拉巴马|阿拉斯加|亚利桑那|阿肯色|加利福尼亚|科罗拉多|康涅狄格|特拉华|佛罗里达|乔治亚|夏威夷|爱达荷|伊利诺伊|印第安纳|爱荷华|堪萨斯|肯塔基|路易斯安那|缅因|马里兰|马萨诸塞|密歇根|明尼苏达|密西西比|密苏里|蒙大拿|内布拉斯加州|内华达|新罕布什尔|新泽西|新墨西哥|纽约|北卡罗来纳|北达科他|俄亥俄|俄克拉荷马|俄勒冈|宾夕法尼亚|罗德岛|南卡罗来纳|南达科他|田纳西|德克萨斯|犹他|佛蒙特|弗吉尼亚|华盛顿|西弗吉尼亚|威斯康星|AL|AK|AZ|AR|CA|CO|CT|DE|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA| MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|西澳|西弗吉尼亚|威|威)))

尝试将第一个单词设为可选会导致表达式仅返回“Springs”,而不是“Palm Springs”,这在上面的表达式中绝对匹配: .*(?i)(?((((,\s|\s{2,})\w+)?(\s\w+)))(?=(,\s+| \s+)

感谢您的帮助!

【问题讨论】:

  • 您使用的是哪个正则表达式实现?
  • 您在这里不是在技术上验证地址(至于您的所有州等),因为您可以简单地输入666 Devils Street, Devil County, HI 66666,因此更广泛的地址可能没问题。
  • willOEM:使用 .NET。

标签: regex


【解决方案1】:

就个人而言,我认为我会采取完全不同的方法。我会将邮政编码视为权威,因为它是您可用的最细粒度的数据。我会得到一个邮政编码到城市映射的列表。提取地址的邮政编码部分。根据邮政编码在新的数据库字段中写入城市和州值。然后编写一个脚本来检查每个数据条目,并确定是否可以在您的字符串中找到基于邮政编码的城市和州名。如果可以,请从字符串中删除这些值。并将该记录标记为已成功处理。如果他们无法将记录标记为您可能需要对其执行人工审核的记录。

另一种替代方法可能是使用像 Google Maps 这样的 API,将您的地址字符串发送到并希望得到一个干净的地址。

【讨论】:

  • Google API 运行良好,但它不是一个选项,因为它的每日限制低于我的需要;再加上 1 年的公司许可证可以满足无限制的请求,费用为 1 万美元。我可能不会选择邮政编码数据库,因为我在 sql server 中使用 RegEx 库。谢谢你!
  • @user2540060 仅仅因为您有一个可用的正则表达式库,并不意味着它是完成这项工作的最佳工具。您仍然没有解决正则表达式如何帮助您处理格式不一致的地址数据的问题。即使是阅读数据的人类,如果不参考权威的城市名称列表,您也可能无法分辨街道的终点和城市的起点。您说您想避免验证,但如果您想通过最少的人工审核来获得尽可能准确的数据,我不知道如何避免某种验证。
【解决方案2】:

这可能过于宽泛,但它可能对您有用,具体取决于您使用的正则表达式实现:

(.+?),\s*(.+?)(?:,\s|\s\s)(.+?)\s(\d{5})

这将从您的示例中返回以下组:

('1977 S. Joshua Tree PL', 'Palm Springs', 'CA', '92264')

【讨论】:

  • 这更接近我正在寻找的东西。唯一的问题是,如果地址没有任何分隔符怎么办?例如:1977 S. Joshua Tree PL Palm Springs CA 92264(应该只解析“Springs”)
  • 如果地址不包含街道和城市之间的任何分隔符,则无法准确拆分两者,除非您还添加额外的验证,例如可接受的城市列表或街道缩写。
  • 是的,我理解它的复杂性。但是,如果我们将其与可接受的城市列表进行比较,那么我们就开始进行验证,我不想这样做。如果一个人输入 Xx Xx Ca 92264.,那么就我而言,这是一个有效的地址。感谢您的帮助!
  • 顺便说一句,当您通过“?:”对分隔符进行分组时,它会做什么?例如:(?:,\s|\s\s)
  • 使用 (?:...) 分组将阻止包含的字符作为匹配组返回。这不适用于所有正则表达式实现。
【解决方案3】:

对于这样的事情,我总是更喜欢命名捕获组。所以试试

(?<addr>[^,]+),\s+(?<city>[^,]+),\s+(?<state>[A-Za-z]{2})\s+(?<zip>\d{5}(-\d{4})?)

解析你的例子,这会给你

  • 地址:1997 S. Joshua Tree PL
  • 城市:棕榈泉
  • 州:加州
  • 邮编:92264

我也支持扩展邮政编码格式。

您可以从这个正则表达式生成的匹配中提取城市组的值。

【讨论】:

  • 感谢您的回复!如果所有地址都以逗号分隔,这将非常有用。但是,有很多地址根本没有任何分隔符,例如:1977 S. Joshua Tree PL Palm Springs CA 92264
  • 你不可能一口气抓住所有东西。最好的办法是运行查询、验证输入、更新数据,然后对剩余的集合运行更多查询,直到可以手动修复剩余问题为止。
  • stack247 - 你是对的,编码的邮政编码仅适用于 5+4 格式的邮政编码。我已将其更正为适用于 5 或​​ 5+4。
猜你喜欢
  • 2020-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多