正则表达式从字符串中提取不一致的邮政编码

Posted

技术标签:

【中文标题】正则表达式从字符串中提取不一致的邮政编码【英文标题】:Regex to extract inconsistent postal codes from string 【发布时间】:2018-10-05 02:13:58 【问题描述】:

使用here 发布的解决方案,我希望从 Excel 中的不规则数据列表中提取邮政编码。

以下是我的数据的示例:

加拿大布兰普顿 L6P 2G9

M5B2R3 多伦多开

加拿大多伦多 M5J 0A6

M1H1T7 加拿大

加拿大多伦多 M4P1T8

MISSISUAGABRAMPTON L5M6S6 加拿大

333 Sea Ray Inisfil l4e2y6 加拿大

要调用函数,我使用以下公式

=RegexExtract(A1,"^(?!.*[DFIOQU])[A-VXY][0-9][A-Z] ?[0-9][A-Z][0-9]$")

但是该功能对我不起作用。我想我需要以某种方式调整我的正则表达式,但我不知道我错过了什么。

【问题讨论】:

IIR,VBA 的正则表达式风格不支持负前瞻断言,您还需要使用链接函数删除锚点。您是要验证邮政编码,还是只是提取它们? 我正在尝试从文本中的任何位置提取它们 【参考方案1】:

google-spreadsheet

试试,

=REGEXEXTRACT(upper(A2), "[A-X]\d[A-Z] ?\d[A-Z]\d")
'alternate
=left(REGEXEXTRACT(upper(A2), "[A-X]\d[A-Z] ?\d[A-Z]\d"), 3)&" "&right(REGEXEXTRACT(upper(A2), "[A-X]\d[A-Z] ?\d[A-Z]\d"), 3)

【讨论】:

这看起来是一个很好的解决方案,但我认为它不适用于 Microsoft Excel excel 没有 RegexExtract 函数,所以我想我会包含一个 google-spreadsheet 标记。该模式确实是您正在寻找的。​​span> 那里的答案很好。+【参考方案2】:

您有 2 个问题。


首先,表达式 - 如果您需要提取邮政编码,您不能使用 ^$ 锚定您的正则表达式。第一个表示“匹配必须出现在字符串的开头”,第二个表示“匹配必须出现在字符串的末尾”。这仅在您验证邮政编码时有用,但它显然不能用于从您的示例中提取邮政编码,因为它们都包含除了邮政编码之外的内容。 正则表达式的另一个问题是否定的前瞻断言(?!.*[DFIOQU]),这意味着“没有匹配可以包含字母 D、F、I、O、Q 或 U”。据我所知,VBScript 正则表达式不支持此功能。如果我弄错了,请在 cmets 中纠正我。

这给了你更迂腐的表达:

[ABCEGHJKLMNPRSTVX]\d[ABCEGHJKLMNPRSTVWXYZ][ -]?\d[ABCEGHJKLMNPRSTVWXYZ]\d

我冒昧地允许在 FSA 和 LDU 之间使用-,因为我看到了很多很多,尤其是来自非加拿大人。


其次,您正在调用的函数(从链接的答案复制如下):

Function RegexExtract(ByVal text As String, _
                      ByVal extract_what As String, _
                      Optional separator As String = ", ") As String

Dim allMatches As Object
Dim RE As Object
Set RE = CreateObject("vbscript.regexp")
Dim i As Long, j As Long
Dim result As String

RE.pattern = extract_what
RE.Global = True
Set allMatches = RE.Execute(text)

For i = 0 To allMatches.count - 1
    For j = 0 To allMatches.Item(i).submatches.count - 1
        result = result & (separator & allMatches.Item(i).submatches.Item(j))
    Next
Next

If Len(result) <> 0 Then
    result = Right$(result, Len(result) - Len(separator))
End If

RegexExtract = result

End Function

第一个问题是它区分大小写。它还专门用于提取您不关心的子匹配 - 您的示例正在寻找单个匹配。

我会选择这个更简单的选项,它也可以正确格式化输出:

Public Function ExtractCanadianPostalCode(inputText As String) As String
    With CreateObject("vbscript.regexp")
        .Pattern = "[ABCEGHJKLMNPRSTVX]\d[ABCEGHJKLMNPRSTVWXYZ][ -]?\d[ABCEGHJKLMNPRSTVWXYZ]\d"
        .IgnoreCase = True
        If .Test(inputText) Then
            Dim matches As Object
            Set matches = .Execute(inputText)
            ExtractCanadianPostalCode = UCase$(Left$(matches(0), 3) & " " & Right$(matches(0), 3))
        End If
    End With
End Function

【讨论】:

"[A-X]\d[A-Z] ?\d[A-Z]\d" 虽然我实际上从未在加拿大邮政编码中看到连字符,但我想世界上有足够多的美国人包含这种可能性。 @Jeeped TBH,如果它们不需要是有效代码,我可能会使用 "[A-Z](\d|O)[A-Z][ -]?(\d|O) [A-Z](\d|O)”。使用“O”表示零是另一个真正常见错误。 是的,我已经看到 OCR 将零转换为哦。这是一个非常有效的观点。 感谢两位的建议。这些解决方案非常适合我。 另外,一个很棒的答案。 +

以上是关于正则表达式从字符串中提取不一致的邮政编码的主要内容,如果未能解决你的问题,请参考以下文章

从 HTML 中提取正则表达式和字符串

C++ 正则检测字串,提取数字以及字符

php 正则表达式 提取字符串内小括号中的数字,只要数字

如何使用正则表达式和外壳从字符串中提取值?

在js中使用正则表达式从字符串中提取正确的用户名

如何在 C# 中使用正则表达式从字符串中提取域名?