我有一个地址类,它使用正则表达式从地址的第一行解析门牌号,街道名称和街道类型.此代码通常运行良好,但我在这里发布与社区分享,看看是否有人有改进建议.
注意:STREETTYPES和QUADRANT常量分别包含所有相关的街道类型和象限.
我在这里包含了一个子集:
private const string STREETTYPES = @"ALLEY|ALY|ANNEX|AX|ARCADE|ARC|AVENUE|AV|AVE|BAYOU|BYU|BEACH|...";
private const string QUADRANTS = "N|NORTH|S|SOUTH|E|EAST|W|WEST|NE|NORTHEAST|NW|NORTHWEST|SE|SOUTHEAST|SW|SOUTHWEST";
Run Code Online (Sandbox Code Playgroud)
HouseNumber,Quadrant,StreetName和StreetType都是该类的所有属性.
private void Parse(string line1)
{
HouseNumber = string.Empty;
Quadrant = string.Empty;
StreetName = string.Empty;
StreetType = string.Empty;
if (!String.IsNullOrEmpty(line1))
{
string noPeriodsLine1 = String.Copy(line1);
noPeriodsLine1 = noPeriodsLine1.Replace(".", "");
string addressParseRegEx =
@"(?ix)
^
\s*
(?:
(?<housenumber>\d+)
(?:(?:\s+|-)(?<quadrant>" +
QUADRANTS +
@"))?
(?:(?:\s+|-)(?<streetname>\S+(?:\s+\S+)*?))??
(?:(?:\s+|-)(?<quadrant>" +
QUADRANTS + @"))?
(?:(?:\s+|-)(?<streettype>" + STREETTYPES +
@"))?
(?:(?:\s+|-)(?<streettypequalifier>(?!(?:" +
QUADRANTS +
@"))(?:\d+|\S+)))?
(?:(?:\s+|-)(?<streettypequadrant>(" +
QUADRANTS + @")))??
(?:(?:\s+|-)(?<suffix>(?:ste|suite|po\sbox|apt)\s*\S*))?
|
(?:(?:po|postoffice|post\s+office)\s+box\s+(?<postofficebox>\S+))
)
\s*
$
";
Match match = Regex.Match(noPeriodsLine1, addressParseRegEx);
if (match.Success)
{
HouseNumber = match.Groups["housenumber"].Value;
Quadrant = (string.IsNullOrEmpty(match.Groups["quadrant"].Value)) ? match.Groups["streettypequadrant"].Value : match.Groups["quadrant"].Value;
if (match.Groups["streetname"].Captures.Count > 1)
{
foreach (Capture capture in match.Groups["streetname"].Captures)
{
StreetName += capture.Value + " ";
}
StreetName = StreetName.Trim();
}
else
{
StreetName = (string.IsNullOrEmpty(match.Groups["streetname"].Value)) ? match.Groups["streettypequalifier"].Value : match.Groups["streetname"].Value;
}
StreetType = match.Groups["streettype"].Value;
//if the matched street type is found
//use the abbreviated version...especially for credit bureau calls
string streetTypeAbbreviation;
if (StreetTypes.TryGetValue(StreetType.ToUpper(), out streetTypeAbbreviation))
{
StreetType = streetTypeAbbreviation;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
享受地址和正则表达式带来的乐趣,您将度过一段漫长而可怕的旅程.
你正试图在混乱中下令.
对于每一个"123简单方式",有一个"14 1/2南".
然后,为了额外的笑声,有盐湖城:"855 South 1300 East".
玩得开心.
在街头地址方面,除了规则之外还有更多例外.
我认为你应该澄清你的使用场景.
除非你处于一个非常非常有限的场景中,你知道地址是按照严格的模式输入的,解析内容的地址是一个非常难以解决的问题,而且通常是徒劳的(除非它是存在的理由)你的申请).
如果您仅限于某个特定国家/地区,该国家/地区具有非常具体的写入地址约定,那么使用这些正则表达式可能会让您获得90%的权限.
但是,一旦你必须开始接受外国地址,你就搞砸了.
即使您是以美国为中心的网站,您也很可能必须能够接受居住在国外的美国公民的地址.
同样,在非常狭窄的领域中可能没问题,但是在用户输入时未经严格验证和约束的地址验证或拆分地址几乎总是一个坏主意.
当你为用户输入一些严格的规则来输入他们的地址时,这些最终结果在一小部分情况下是不合适的,即使在最好的地址验证组件中也是如此.
只是搞乱地址解析的一些事情:
底线是
如果以可解析的格式获取地址非常重要,请100%确定您可以正确获得所有可能的组合,否则您将失去一定比例的失败,这将意味着用户和销售损失.
如果您没有100%的案例覆盖率,则不要对用户强制执行严格的规则.
我无法计算我放弃购买的网站数量,因为当我居住的地方没有时,他们会要求邮政编码.
对于咆哮很抱歉,但我认为重要的是,想要进行地址验证和解析的人都要认真考虑自己所处的问题.