Regex для разделения немецкого адреса на части - PullRequest
6 голосов
/ 26 марта 2012

Добрый вечер,

Я пытаюсь разбить части немецкой адресной строки на ее части с помощью 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)

Было бы идеально, если бы система / регулярное выражение все еще работало, если бы отсутствовали такие части, как почтовый индекс или город.

Существует ли какое-либо регулярное выражение или библиотека, с которой я мог бы заархивировать это?

EDIT: Правило для немецких адресов:
Улица: символы, цифры и пробелы
Номер дома: номер и любые символы (или пробел) до серии цифр (индекс) (по крайней мере, в этих примерах)
Индекс: 5 цифр
Место или город: остальные могут быть также с пробелами, запятыми или фигурными скобками

Ответы [ 6 ]

12 голосов
/ 30 марта 2012

Я столкнулся с подобной проблемой и немного подправил решения, представленные здесь, и пришел к этому решению, которое также работает, но (imo) немного проще для понимания и расширения:

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

Вот несколько примеров примеров .

. Он также может обрабатывать пропущенные номера улиц и легко расширяется путем добавления специальных символов в классы символов.

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

После этоготам должен быть почтовый индекс, который является единственной частью, которая абсолютно необходима, потому что это единственная постоянная часть.Все после почтового индекса считается названием города.

5 голосов
/ 26 марта 2012

Я бы начал со спины, поскольку, насколько мне известно, название города не может содержать цифр (но оно может содержать пробелы (первый найденный мной пример: « Weil derStadt ”). Затем пятизначным числом перед этим должен быть почтовый индекс.

Число (возможно, сопровождаемое одной буквой) перед этим является номером улицы. Обратите внимание, что это также может быть диапазон . Все, что до этого является названием улицы.

В любом случае, здесь мы идем:

^((?:\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 не поддерживает это.Это s * cks, потому что оно эффективно делает сложные регулярные выражения непригодными для использования.

Тем не менее, вот несколько более разборчивое регулярное выражение:

^
(?<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>[^\\)]+)\\))?" +
    "$";
2 голосов
/ 26 марта 2012

Вот мое предложение, которое может быть доработано, например, для разрешения отсутствующих частей.

Шаблон регулярного выражения:

^([^0-9]+) ([0-9]+.*?) ([0-9]{5}) (.*)$
  • Группа 1: Улица
  • Группа 2: Дом №.
  • Группа 3: ZIP
  • Группа 4: Город
1 голос
/ 26 марта 2012
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");
                }

Я думаю, это не работает с немецкими умлаутами, но вы можете это исправить самостоятельно. В любом случае, это хороший стартап.

Я рекомендую посетить этот это отличный сайт о регулярных выражениях. Удачи!

0 голосов
/ 26 марта 2012

попробуйте это:

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

Он захватывает группы для каждого из пробелов, которые разделяют 1 из 4 разделов адреса

OR

этот дает вам группы для каждой части адреса:

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

Я не знаю java, поэтому не уверен, какой именно код использовать для замены захваченных групп.

0 голосов
/ 26 марта 2012

На первый взгляд кажется, что это можно сделать простым пробелом, однако, если присмотреться, я замечаю, что адрес всегда состоит из 4 частей, а первая часть может иметь пробел.

Я бы сделал что-то вроде этого (psudeocode):

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

Однако это будет обрабатывать только одну форму адреса. Если адреса пишутся несколькими способами, это может быть намного сложнее.

...