【问题标题】:Regex for splitting a german address into its parts用于将德国地址拆分为多个部分的正则表达式
【发布时间】:2013-06-13 06:53:49
【问题描述】:

晚上好,

我正在尝试通过 Java 将德语地址字符串的各个部分拆分为各个部分。有谁知道一个正则表达式或一个库来做到这一点?拆分如下:

Name der Straße 25a 88489 Teststadt
到
Name der Straße|25a|88489|Teststadt

或

Teststr. 3 88489 Beispielort (Großer Kreis)
致
Teststr.|3|88489|Beispielort (Großer Kreis)

如果缺少邮政编码或城市等部分,如果系统/正则表达式仍然有效,那将是完美的。

是否有任何正则表达式或库可供我存档?

编辑:德国地址规则:
街道:字符、数字和空格
房屋编号:数字和任何字符(或空格),直到一系列数字(zip)(至少在这些示例中)
邮编:5 位数
地点或城市:其余部分也可能带有空格、逗号或大括号

【问题讨论】:

  • 对于不熟悉德国地址的人,规则是什么?是“有空格但没有数字的东西”、“有数字但没有空格的东西”、“有数字但没有空格”、“没有数字但没有空格”吗?
  • 您不需要正则表达式。只需使用空格分隔符拆分字符串,然后使用条形 | 分隔符将其加入 - 但 Oli 上面的评论也是相关的,因为我假设德国地址是用空格分隔的
  • @OliCharlesworth:编辑了帖子
  • @Robbie:我不能只用空格分隔它们,因为街道名称和城市/地点也可以包含空格。
  • 不要认为这很容易。有很多带有空格的街道名称。此外,有些人写“25 a”而不是“25a”。我通常会用“,”写我的地址来分隔各个部分。您是否以定义的格式从其他系统获取地址?

标签: java regex split street-address


【解决方案1】:

我遇到了一个类似的问题,并稍微调整了这里提供的解决方案,并得出了这个同样有效的解决方案,但 (imo) 更易于理解和扩展:

/^([a-zäöüß\s\d.,-]+?)\s*([\d\s]+(?:\s?[-|+/]\s?\d+)?\s*[a-z]?)?\s*(\d{5})\s*(.+)?$/i

这里有一些example matches。

它还可以处理丢失的街道号码,并且可以通过向字符类添加特殊字符来轻松扩展。

[a-zäöüß\s\d,.-]+?                         # Street name (lazy)
[\d\s]+(?:\s?[-|+/]\s?\d+)?\s*[a-z]?)?     # Street number (optional)

之后,必须有邮政编码,这是唯一绝对必要的部分,因为它是唯一不变的部分。邮政编码后的所有内容都被视为城市名称。

【讨论】:

    【解决方案2】:

    我会从后面开始,因为据我所知,城市名称不能包含数字(但它可以包含空格(我发现的第一个示例:“Weil der Stadt” )。那么前面的五位数字一定是邮政编码。

    前面的数字(可能后跟一个字母)是门牌号。请注意,这也可以是一个范围。 在此之前的任何内容都是街道名称。

    不管怎样,我们开始吧:

    ^((?:\p{L}| |\d|\.|-)+?) (\d+(?: ?- ?\d+)? *[a-zA-Z]?) (\d{5}) ((?:\p{L}| |-)+)(?: *\(([^\)]+)\))?$
    

    这甚至可以正确解析神秘的地址,例如“Straße des 17. Juni 23-25 a 12345 Berlin-Mitte”。

    请注意,这不适用于地址扩展名(例如“Gartenhaus”或“c/o ...”)。我不知道如何处理这些。我相当怀疑是否有一个可行的正则表达式来表达这一切。

    如您所见,这是一个非常复杂的正则表达式,包含许多捕获组。 如果我会在代码中使用这样的表达式,我会使用命名捕获(Java 7 支持它们)并使用x 标志将表达式分解为更小的部分。不幸的是,Java 不支持这一点。这很糟糕,因为它有效地使复杂的正则表达式无法使用。

    不过,这里有一个更清晰的正则表达式:

    ^
    (?<street>(?:\p{L}|\ |\d|\.|-)+?)\ 
    (?<number>\d+(?:\ ?-\ ?\d+)?\ *[a-zA-Z]?)\ 
    (?<zip>\d{5})\ 
    (?<city>(?:\p{L}|\ |-)+)
    (?:\ *\((?<suffix>[^\)]+)\))?
    $
    

    在 Java 7 中,我们可以实现的最接近的是(未经测试;可能包含拼写错误):

    String pattern =
        "^" +
        "(?<street>(?:\\p{L}| |\\d|\\.|-)+?) " +
        "(?<number>\\d+(?: ?- ?\\d+)? *[a-zA-Z]?) " +
        "(?<zip>\\d{5}) " +
        "(?<city>(?:\\p{L}| |-)+)" +
        "(?: *\\((?<suffix>[^\\)]+)\\))?" +
        "$";
    

    【讨论】:

    • 对你的街道字符串来说就像一个魅力,但不幸的是,它不适用于示例街道。您可以使用 radzio 的代码示例和您的正则表达式(带有转义部分)^((?:\\p{L}| |\\d|\\.|-)+?) ((?:\\d+ ?- ?)\\d+ *[a-zA-Z]?) (\\d{5}) ((?:\\p{L}| |-)+)$ 对其进行测试
    • @Christian 因为我是个白痴。再试一次,我把街道号码范围写错了,没有让它成为可选的。它现在适用于示例地址。
    • 找到一个缺失的部分。有时在定义区域的地方有大括号“(”和“)”。它们不是官方地址的一部分,但可以在此类数据中找到。是否可以将其添加到正则表达式中?如果,如何?
    • @Christian 嗯,你到底在哪里有括号?请用示例编辑问题。
    • 可以说这个地方可以由任何字符组成,除了数字吗?因为我找到了以下地址:“Schwabacher Str. 22 48516 Eschborn, Taunus”。带有逗号“,”的地址。这不适用于正则表达式。
    【解决方案3】:

    这是我的建议,可以进一步微调,例如允许丢失的部分。

    正则表达式模式:

    ^([^0-9]+) ([0-9]+.*?) ([0-9]{5}) (.*)$
    
    • 第一组:街道
    • 第 2 组:房屋编号。
    • 第 3 组:邮编
    • 第 4 组:城市

    【讨论】:

    • 此正则表达式已损坏,因为街道名称可以包含数字。例如(但不限于),街道可以在分配名称之前进行编号,以便您最终得到“Straße 42”。另一个例子是“Straße des 17. Juni”。
    • OP 没有在街道名称中提及数字。也许没有必要为那些持有?
    • @KonradRudolph 你是对的。这是一种完全让我忘记的可能性。是否有一个“系统”可以用来定义德国地址的构建方式?
    • @KonradRudolph 这个问题清楚地将街道部分定义为“街道:字符和空格直到一个数字”,所以我的正则表达式没有被破坏。我刚刚回答了这个问题。如果正如 Christian 所证实的那样,考虑到这部分问题,问题不正确,则可能需要不同的解决方案,但我也会要求 Christian 改变问题。
    • @Michael 是的,问题没有正确指定输入。正则表达式在实际输入中仍然被破坏。不是你的错,仍然如此。
    【解决方案4】:
    public static void main(String[] args) {
        String data = "Name der Strase 25a 88489 Teststadt";
        String regexp = "([ a-zA-z]+) ([\\w]+) (\\d+) ([a-zA-Z]+)";
    
        Pattern pattern = Pattern.compile(regexp);
        Matcher matcher = pattern.matcher(data);
        boolean matchFound = matcher.find();
    
        if (matchFound) {
            // Get all groups for this match
            for (int i=0; i<=matcher.groupCount(); i++) {
                String groupStr = matcher.group(i);
                System.out.println(groupStr);
            }
        }System.out.println("nothing found");
                    }
    

    我猜它不适用于德语变音符号,但您可以自行解决此问题。无论如何,这是一个很好的创业公司。

    我建议访问this,这是一个关于正则表达式的好网站。祝你好运!

    【讨论】:

    • 这不起作用,原因与上面的其他正则表达式不起作用。
    • 你是指可以容纳数字的街道名称?我想问题中没有明确说明。
    • 例如。还有更多疯狂的事情发生。德国地址非常复杂。详情看我的回答。
    • 如果 String data = "88489 Teststadt Name der Strase 25a "怎么办?正则表达式模式将如何?谢谢
    【解决方案5】:

    乍一看,它看起来像是一个简单的空格,但仔细观察我发现地址总是有 4 部分,第一部分可以有空格。

    我会做的是这样的(伪代码):

    address[4] = empty
    split[?] = address_string.split(" ")
    address[3] = split[last]
    address[2] = split[last - 1]
    address[1] = split[last - 2]
    address[0] = join split[first] through split[last - 3] with whitespace, trim trailing whitespace with trim()
    

    但是,这只会处理一种形式的地址。如果地址以多种方式写入,则可能会更加棘手。

    【讨论】:

      【解决方案6】:

      试试这个:

      ^[^\d]+[\d\w]+(\s)\d+(\s).*$
      

      它为分隔地址的 4 个部分中的 1 个的每个空格捕获组

      或

      这个为您提供每个地址部分的组:

      ^([^\d]+)([\d\w]+)\s(\d+)\s(.*)$
      

      我不懂 java,所以不确定用于替换捕获组的确切代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-22
        • 2019-04-11
        • 1970-01-01
        • 2019-05-14
        • 2014-01-30
        • 2019-10-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多