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

时间:2018-10-05 02:13:59

标签: regex excel vba function postal-code

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

以下是我的数据的示例:

  

Brampton 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]$")

但是该功能不适用于我。我想我需要以某种方式调整我的正则表达式,但是我不知道我缺少什么。

2 个答案:

答案 0 :(得分:3)

您有2期。


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

这会给您带来一些古怪的表情:

[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

答案 1 :(得分:3)

尝试

=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)

enter image description here