Vim:解析来自全球各地的地址字段

时间:2012-01-07 18:45:56

标签: regex parsing vim substitution street-address

简介

这篇文章很长,但我认为这很彻底。我希望这篇文章在教授复杂的VIM正则表达式时可能对其他人有用(地址)。谢谢你的时间。

全球地址:

美国,加拿大和其他一些国家/地区在表单上提供了5个字段,然后以逗号分隔的格式显示,我需要进一步剖析。理想情况下,逗号分隔的内容如下所示:

  

一些非常好的地方,111街,美丽的城镇,StateOrProvince,zip

其中zip可以是一系列正数(美国),也可以是数字和字母(加拿大)。

人们总是在文本框字段输入中添加额外的逗号,这会增加解析此数据的复杂性。例如:

  

一些非常好的地方,111街,套房101,美丽的城镇,StateOrProvince,zip

这一解析进一步复杂化的是,来自非美国和非加拿大国家的数据包含一个额外的逗号分隔字段,以某种方式提供给他们 - 为他们添加一个进入他们国家的地方。 (不,没有"美国"或者#34;加拿大"字段用于他们的参赛作品。所以,它"另外"对于原来的5个逗号 - 分隔字段。)例如:

  

建筑物的外国名称,街道名称,城市,邮编,国家

" ,,"通常是空的,因为非美国国家没有分割成州。并且,是的,相同的"额外的逗号"如上所述也发生在这里。

  

建筑物的外国名称,交叉街道,地区,街道名称,城市,邮编,国家

解析策略:

国家/地区名称永远不会包含数字,而美国或加拿大邮政编码始终至少包含一些数字。如果你使用这个关于最后一个字段内容的假设倒退,那么你应该能够将国家,邮政编码,州(如果不是空的" ,,"),城市和街道置于他们尊重的位置 - 这是最重要的领域。超出这些部分的任何内容都可以作为地址的描述(即建筑物,名称,套房,十字路口等)集中在第一行或两行中。例如:

  

一些非常好的地方,111街,101套房,美丽的小镇,可爱的州,数字和字母

  1. 最后一部分有一个数字(因此是美国或加拿大地址)
  2. 共有6个部分,因此比原来的5个部分多一个
  3. 知道第5-2节是拉链,州,镇,地址......
  4. 6减5(原始)=添加一个额外的地址(地址2)字段并将第一部分保留为标题,结果是:
  5. 标题:一些非常好的地方,地址1:111街,地址2:套房101,镇:美丽的城镇,州/省:可爱的州,邮编:数字和字母

    然而,在哪里" 111 Street"可能存在差异。或者" Suite 101"去(地址1或地址2),它至少将拉链,州,城市和地址集中在一起,并将第一部分作为"标题"到电子邮件地址以进行数据输入。

    根据这种方法,外部地址被解析为:

      

    建筑物的外国名称,街道,街道,街道名称,A   City ,, zip,Country

    1. 上一部分没有数字,因此必须是国家/地区
    2. 这意味着,从右向左移动,第二部分是zip
    3. 所以现在(外国)你有一个"原来的6个部分"从示例中的总数7中减去
    4. 第7部分=国家,第6部分= zip,第5部分=州(外国地址大部分为空白),第4名=城市,第3名=地址1,第2名=地址2,第1名=标题
    5. 我们知道使用两个地址字段,因为该示例有7个部分,外部地址有6个部分。基数上方的任意数量的部分被添加到第二个地址2字段。如果基本部分计数上方有3个部分,则它们将附加到address2字段内的每个部分。
    6. 编码

      在使用VIM的这种方法中,我最初如何读取逗号分隔部分的数量(在我已经捕获了寄存器中的整个地址之后)?如何在一系列逗号分隔的部分上进行子匹配,我不确定存在的部分数量?

      示例地址

      如果你愿意提供帮助,这里有一些练习地址(美国和外国):

      City Gas& Electric - Bldg 4,222 Middle Park Ct,CP4120F,Dallas,Texas,44984

      MHG Engineering,Inc。Suite 200,9899 Balboa Ave,San Diego,California,92123-1502

      SolarWind Turbines,2楼会议室,2300 Ruffin Road,Seattle,Washington,84444

      123 Aeronautics,2239 Industry Parkway,Salt Lake City,Utah,55344

      Ongwanda Gov& t Resources,6000 Portsmouth Avenue,Ottawa,Ontario,K7M 8A6

      Graylang Seray Centre,6600 Haig Rd,Singapore,437848,新加坡

      马来西亚古晋佩特拉再也Jalan Sultan Tengah 14座459号,邮编:93050,马来西亚

      Virtual Steel,1 Umgazi Rd Aspec Park,Pretoria,0075,南非

      Idiom Towers南,五楼,Jasmen会议室,1500 Freedom Street,Pretoria,0002,南非

2 个答案:

答案 0 :(得分:1)

也许你应该回顾一些关于世界各地地址的其他问题。美国和加拿大的系统非常系统化;大多数其他国家对批准的格式不太严格。你为美国和加拿大设计的任何东西都会在你处理其他地址时立即遇到问题。

可能还有其他相关问题:请参阅标记street-address了解其中一些问题。

答案 1 :(得分:1)

以下代码是一个草稿质量的Vim脚本(希望如此)实现 问题中描述的地址解析例程。

function! ParseAddress(line)
    let r = split(a:line, ',\s*', 1)
    let hadcountry = r[-1] !~ '\d'
    let a = {}
    let a.country = hadcountry ? r[-1] : ''
    let r = r[:-1-hadcountry]
    let a.zip = r[-1]
    let a.state = r[-2]
    let a.city = r[-3]
    let a.header = r[0]
    let nleft = len(r) - 4
    if hadcountry
        let a.address1 = r[-4]
        let a.address2 = join(r[1:nleft-1], ', ')
    else
        let a.address1 = r[1]
        let a.address2 = join(r[2:nleft], ', ')
    endif
    return a
endfunction

function! FormatAddress(a)
    let t = map([
    \   ['Header', 'header'],
    \   ['Address 1', 'address1'],
    \   ['Address 2', 'address2'],
    \   ['Town', 'city'],
    \   ['State/Province', 'state'],
    \   ['Country', 'country'],
    \   ['Zip', 'zip']],
    \   'has_key(a:a, v:val[1]) && !empty(a:a[v:val[1]])' .
    \       '? v:val[0] . ": " . a:a[v:val[1]] : ""')
    return join(filter(t, '!empty(v:val)'), '; ')
endfunction

以下命令可用于测试上述解析例程。

:g/\w/call setline(line('.'), FormatAddress(ParseAddress(getline('.'))))

(可以为:global命令提供一个范围来运行它 测试地址行数。)