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

Regex 正则表达式从字符串中提取不一致的邮政编码,regex,excel,vba,function,postal-code,google-spreadsheet,Regex,Excel,Vba,Function,Postal Code,Google Spreadsheet,使用posted解决方案,我希望从Excel中的不规则数据列表中提取邮政编码 下面是我的数据的示例: 加拿大布兰顿L6P 2G9 M5B2R3多伦多酒店 加拿大多伦多M5J 0A6 M1H1T7加拿大 加拿大多伦多M4P1T8 加拿大密西西比州兰普顿L5M6S6 333加拿大海鱼协会l4e2y6 要调用该函数,我使用以下公式 =RegexExtract(A1,"^(?!.*[DFIOQU])[A-VXY][0-9][A-Z] ?[0-9][A-Z][0-9]$") 但是,该

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

下面是我的数据的示例:

加拿大布兰顿L6P 2G9

M5B2R3多伦多酒店

加拿大多伦多M5J 0A6

M1H1T7加拿大

加拿大多伦多M4P1T8

加拿大密西西比州兰普顿L5M6S6

333加拿大海鱼协会l4e2y6

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

=RegexExtract(A1,"^(?!.*[DFIOQU])[A-VXY][0-9][A-Z] ?[0-9][A-Z][0-9]$")
但是,该功能不适用于我。我想我需要以某种方式调整我的正则表达式,但我不知道我缺少了什么。

您有两个问题


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

这给了你一个稍微有点迂腐的表达:

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

我自由选择允许FSA和LDU之间的
-
,因为我看到了很多,特别是非加拿大人


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

试试看


IIR,VBA的正则表达式风格不支持消极的前瞻断言,您还需要删除带有链接函数的锚。你是想验证邮政编码,还是仅仅提取它们?我想从文本
“[A-X]\d[A-Z]?\d[A-Z]\d”
中的任何位置提取它们。虽然我从来没有在加拿大邮政编码中看到过连字符,但我想世界上有足够多的美国人将这种可能性包括在内。@jeepd TBH,如果它们不需要是有效的代码,我可能会使用“[A-Z](\d | O)[A-Z][-]?(\d | O)[A-Z](\d | O)”。使用“O”表示零是另一个非常常见的错误。是的,我见过OCR将零转换为oh。这一点很有道理。谢谢你们两位的建议。这些解决方案对我来说非常有效。另外,一个很棒的ans。+这看起来是一个非常好的解决方案,但是我认为它在Microsoft Excel中不起作用。Excel没有RegexExtract函数,所以我想我应该包括一个google电子表格标签。这个模式正是你想要的。很好的答案+
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
=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)