【问题标题】:Using RegEx to parse legal description from address field使用 RegEx 解析地址字段中的合法描述
【发布时间】:2020-11-14 14:12:11
【问题描述】:

不幸的是,我需要从最初输入到遗留数据库的单个字段中的数据中解析出单个地址元素。现在,我正在尝试通过将信息拆分为适当的字段(街道地址、城市、州、邮政编码)来规范化我们公司所有未来开发项目的数据(用于历史报告等)。然而,我必须处理的一些地址只不过是对房产的合法描述——例如,Lot 1, Block 1, Somecity, ST, 74999S1-T1-R1, Anothercity, St, 74998

我相信我实际上大部分的标准地址信息解析工作得相当好,但有一个我不确定如何完成,主要是因为我对 RegEx 相对不熟悉.我想做的是在尝试从字段的剩余值中解析任何其他信息之前提取这些法律描述。我知道我的模式会“看起来像”什么,但我不确定如何构建实际的 RegEx 模式。

我知道我将与一些捕获组合作,但我完全不知道如何设置它以匹配我想要看到的内容。我尝试过使用 ^((L(\w\s)*\d+(\w*\d*\s*)?)(B(\w\s)*\d+(\w*\d*\s*)?)?\,) 之类的东西,但显然不是这样(请参阅我的 testing on Regexr)。我只是不太了解 RegEx 语法,还不知道我在做什么“错误”。

以下是我想在 RegEx 中使用的模式规则。我意识到这些可能是数据上的两个单独的“传递” - 一次是寻找 LOT/BLOCK 符号,然后再次寻找 SECTION/TOWNSHIP/RANGE 符号- 但这完全没问题。我也明白,在获取数据时,没有什么是绝对 100% 准确的,我将处理一些“错误”匹配,甚至是“错过”匹配,这些匹配必须手动处理,但是让这个 RegEx 提取在规范化我的数据方面,我能做的将是一个巨大的开端。在这一点上,我只是试图在解析其余数据之前从地址中消除任何“额外”元素。

RegEx 应该在修剪后的字符串(没有前导或尾随空格)的最开始找到这些模式作为合法描述 - 至少在这个特定的数据库中 - 不会被在地址字符串中发现比开头“晚”。


匹配规则 - 批次/区块法律说明

  • 修剪后的大写字符串的第一个字符是“L
    • 按此顺序,“L”后跟:
      • 零个或多个字母字符或空格(例如、“LOT”、“LOTS”、“LT”等)
      • 必须包含一个或多个数值
    • 可能在第一个数字字符(或这些字符的某种组合)之后有另一个数字、逗号、破折号或空格
  • 上述可能后跟一个“B”字符
    • 按此顺序,“B”后跟:
      • 零个或多个字母字符或空格(例如、“BLK”、“BLOCK”、“BLCK”等)
      • 必须包含一个或多个数值
  • 合法描述应以逗号(表示下一个地址元素)或字符串结尾结束。 BLOCK 组和此终止之间的任何字符应包含在法律描述中(尾随逗号不应 em> 被包括在内)。

匹配规则 - 部分/城镇/范围法律说明

  • 修剪后的大写字符串的第一个字符是“S
    • 在此顺序中,“S”后跟:
      • 零个或多个字母字符或空格(例如、“SECTION”、“SEC”、“SECT”等)
      • 一个或多个数值
    • 可能在第一个数字字符之后是另一个数字、逗号、破折号或空格
  • 上述可能后跟一个“T”字符
    • 如果存在,按此顺序,“T”后面将是:
      • 零个或多个字母字符或空格(例如、“TWNSHP”、“TOWN”、“TWN”等)
      • 必须包含一个或多个数值
      • 零个或多个字母字符或空格
    • 如果“T”字符不存在且字符串未终止(见下文),则要查找的下一个字符应该是数字
  • 上述可能后跟一个“R”字符
    • 按此顺序,“R”后面将是:
      • 零个或多个字母字符或空格(例如、“RANGE”、“RNG”、“RG”等)
      • 必须包含一个或多个数值
      • 零个或多个字母字符或空格
    • 如果“R”字符不存在且字符串未终止(见下文),则要查找的下一个字符应该是数字
  • 合法描述应以逗号(表示下一个地址元素)或字符串结尾结束。 RANGE”组和此终止符之间的任何字符应包含在法律描述中(尾随逗号不应 em> 被包括在内)。

这是我正在使用的一些(稍微混淆的)示例数据:


样本数据 - 批次/区块法律说明

1.    L2 B64,SOMECITY ,OK,74999
2.    L2 B4 RHODA 1 ADDN,SOMECITY,OK,74999 - 81 HILLCREST MH
3.    L20-22 B10 LETCHERS ADDN,SOMECITY,OK,74999
4.    L2 S10-13-18,SOMECITY,OK,74999
5.    L23&24 B10, SOMECITY, OK, 74999
6.    L21 OAKMONT ADD, SOMECITY OK, 74999
7.    L24-30 B42,SOMECITY,OK,74999
8.    L24 DOGWOOD ESTATES
9.    L27 B2 LAKE RHONDA, 82 SKYLINE MH
10.   L3 B2 STONEBROOK II ADDN, SOMECITY, OK, 74999
11.   LOT 22 BLOCK 1 OF BEACON,SOMECITY,OK,74999
12.   LOT 44-45 WILLIAM DR,SOMECITY,OK,74999
13.   L 10,11 B17,SOMECITY,OK
14.   L 8 B 4 HISEL EST.

结果应该是:

1.    L2 B64
2.    L2 B4 RHODA 1 ADDN
3.    L20-22 B10 LETCHERS ADDN
4.    L2 S10-13-18
5.    L23&24 B10
6.    L21 OAKMONT ADD
7.    L24-30 B42
8.    L24 DOGWOOD ESTATES
9.    L27 B2 LAKE RHONDA
10.   L3 B2 STONEBROOK II ADDN
11.   LOT 22 BLOCK 1 OF BEACON
12.   LOT 44-45 WILLIAM DR
13.   L 10,11 B17
14.   L 8 B 4 HISEL EST.

样本数据 - 区域/城镇/范围法律说明

1.    S18-31-21,ANOTHERCITY,OK,74998
2.    S2 T6N R1E INDIAN MERIDIAN CLEVELAND CO
3.    S20-T12N-R16E-MCINTOSH CO,ANOTHERCITY,OK,74998
4.    S20,T12N,R19E,MUSKOGEE CO
5.    S2,T15,R25, 86 REGAL 14X60 MH CFC2086F4KL100000
6.    S18-31-21,ANOTHERCITY,OK,74998
7.    S21 T6N R1E
8.    S21 T6N R1E,ANOTHERCITY,OK,74998
9.    SEC 33 TWP 19 RNG 19-BARN,ANOTHERCITY,OK,74998
10.   SECT 1-22-22 METAL BARN,ANOTHERCITY,OK,74998

结果应该是:

1.    S18-31-21
2.    S2 T6N R1E INDIAN MERIDIAN CLEVELAND CO
3.    S20-T12N-R16E-MCINTOSH CO
4.    S20,T12N,R19E
5.    S2,T15,R25
6.    S18-31-21
7.    S21 T6N R1E
8.    S21 T6N R1E
9.    SEC 33 TWP 19 RNG 19-BARN
10.   SECT 1-22-22 METAL BARN

如果您需要任何其他信息,请随时告诉我。正如我上面所说,我意识到 RegEx 不会成为我需要做的 100% 准确的“万灵药”,但我真的希望它至少能给我一个重要的开端,所以我不必手动清理数十万条记录。

【问题讨论】:

  • 它是Zero or more alpha characters OR spaces 即:[a-z ]* 与它一起使用 and 意味着包含 0 次或更多次。
  • 例如,S\d+(?:-| |,)(?:T\d+\w*|\d+-*\d*)(?:,R| R|-R)*(?:\d+\w*)(?:-| )?[A-Z ]*? (只是写在这里,基于instructions,所以...)。第一个 sample 似乎停在第一个逗号处。
  • 对于 LOT BLOCK 我本来想说这个 L[A-Z 0-9]*[0-9][A-Z 0-9-]* 但是当我看到你匹配 L23&24 B10 时我突然意识到这是匹配你的样本的正则表达式说L[^,]*
  • 对,我之前没看到最后两行。不过,它会稍微改变:S[A-Z]*\d*(?:-| |,)*(?:T\d*\w*|\d+-*\d*|\w* )*(?:,R| R|-R)*\d+\w*(?:-| )?[A-Z ]*。虽然它可以改进很多,但有几个子模式......事实上,它有点慢
  • 在集合中不断添加允许的字符没关系,原理是一样的,总是允许到第一个逗号,这是唯一的常量边界。当然,它必须调整为仅匹配 BOL 而不是跨行:(?<!\S)L[^,\r\n]*

标签: regex vb.net parsing regex-group street-address


【解决方案1】:

简单地匹配直到第一个逗号, 的所有内容都会产生您在23 示例中寻找21 的结果:^(?:(?!,).)*

const data = [
  {
    "inputted": "1.    L2 B64,SOMECITY ,OK,74999",
    "expected": "1.    L2 B64"
  },
  {
    "inputted": "2.    L2 B4 RHODA 1 ADDN,SOMECITY,OK,74999 - 81 HILLCREST MH",
    "expected": "2.    L2 B4 RHODA 1 ADDN"
  },
  {
    "inputted": "3.    L20-22 B10 LETCHERS ADDN,SOMECITY,OK,74999",
    "expected": "3.    L20-22 B10 LETCHERS ADDN"
  },
  {
    "inputted": "4.    L2 S10-13-18,SOMECITY,OK,74999",
    "expected": "4.    L2 S10-13-18"
  },
  {
    "inputted": "5.    L23&24 B10, SOMECITY, OK, 74999",
    "expected": "5.    L23&24 B10"
  },
  {
    "inputted": "6.    L21 OAKMONT ADD, SOMECITY OK, 74999",
    "expected": "6.    L21 OAKMONT ADD"
  },
  {
    "inputted": "7.    L24-30 B42,SOMECITY,OK,74999",
    "expected": "7.    L24-30 B42"
  },
  {
    "inputted": "8.    L24 DOGWOOD ESTATES",
    "expected": "8.    L24 DOGWOOD ESTATES"
  },
  {
    "inputted": "9.    L27 B2 LAKE RHONDA, 82 SKYLINE MH",
    "expected": "9.    L27 B2 LAKE RHONDA"
  },
  {
    "inputted": "10.   L3 B2 STONEBROOK II ADDN, SOMECITY, OK, 74999",
    "expected": "10.   L3 B2 STONEBROOK II ADDN"
  },
  {
    "inputted": "11.   LOT 22 BLOCK 1 OF BEACON,SOMECITY,OK,74999",
    "expected": "11.   LOT 22 BLOCK 1 OF BEACON"
  },
  {
    "inputted": "12.   LOT 44-45 WILLIAM DR,SOMECITY,OK,74999",
    "expected": "12.   LOT 44-45 WILLIAM DR"
  },
  {
    "inputted": "13.   L 10,11 B17,SOMECITY,OK",
    "expected": "13.   L 10,11 B17"
  },
  {
    "inputted": "14.   L 8 B 4 HISEL EST.",
    "expected": "14.   L 8 B 4 HISEL EST."
  },
  {
    "inputted": "1.    S18-31-21,ANOTHERCITY,OK,74998",
    "expected": "1.    S18-31-21"
  },
  {
    "inputted": "2.    S2 T6N R1E INDIAN MERIDIAN CLEVELAND CO",
    "expected": "2.    S2 T6N R1E INDIAN MERIDIAN CLEVELAND CO"
  },
  {
    "inputted": "3.    S20-T12N-R16E-MCINTOSH CO,ANOTHERCITY,OK,74998",
    "expected": "3.    S20-T12N-R16E-MCINTOSH CO"
  },
  {
    "inputted": "4.    S20,T12N,R19E,MUSKOGEE CO",
    "expected": "4.    S20,T12N,R19E"
  },
  {
    "inputted": "5.    S2,T15,R25, 86 REGAL 14X60 MH CFC2086F4KL100000",
    "expected": "5.    S2,T15,R25"
  },
  {
    "inputted": "6.    S18-31-21,ANOTHERCITY,OK,74998",
    "expected": "6.    S18-31-21"
  },
  {
    "inputted": "7.    S21 T6N R1E",
    "expected": "7.    S21 T6N R1E"
  },
  {
    "inputted": "8.    S21 T6N R1E,ANOTHERCITY,OK,74998",
    "expected": "8.    S21 T6N R1E"
  },
  {
    "inputted": "9.    SEC 33 TWP 19 RNG 19-BARN,ANOTHERCITY,OK,74998",
    "expected": "9.    SEC 33 TWP 19 RNG 19-BARN"
  },
  {
    "inputted": "10.   SECT 1-22-22 METAL BARN,ANOTHERCITY,OK,74998",
    "expected": "10.   SECT 1-22-22 METAL BARN"
  }
];

const regExp = /^(?:(?!,).)*/;

let matches = 0;
const total = data.length;
data.forEach(({ inputted: input, expected }, i) => {
  const match = input.match(regExp)?.[0];
  console.log(i + 1 + ') matched ', match);
  console.log((i < 10 ? '   ' : '    ') + 'expected', expected);
  matches += match == expected;
});
const successRate = ((matches / total) * 100).toFixed(2);
console.log(successRate + '% success rate');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-28
    • 2020-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    相关资源
    最近更新 更多