Регулярное выражение для извлечения (австрийской) улицы номер дома / лестницы / этажа / двери - PullRequest
3 голосов
/ 05 августа 2020

Мне нужно извлечь номер дома со всеми различными созвездиями в Австрии:

|               Street name               | housenumber | stairs | floor | door |
| --------------------------------------- | ----------- | ------ | ----- | ---- |
| Lilienstr. 12a                          | 12a         |        |       |      |
| Leibnizstraße 36/28/2                   | 36          | 28     |       | 2    |
| Prager Straße 14/3/1/4                  | 14          | 3      | 1     | 4    |
| Guentherstr. 43 B                       | 43 B        |        |       |      |
| Eberhard-Leibnitz Str. 1/7              | 1           |        |       | 7    |
| Schießstätte 7/7                        | 7           |        |       | 7    |

Я уже нашел этот вопрос: Regex для извлечения (немецкого) номера улицы .

Работает, если не введена ни одна лестница / этаж / дверь. Вы можете помочь?

^[ \-0-9a-zA-ZäöüÄÖÜß.]+?\s+(\d+(\s?[a-zA-Z])?)\s*(?:$|\(|[A-Z]{2})

Ответы [ 3 ]

1 голос
/ 06 августа 2020

Кредиты для ядра шаблона с использованием дополнительных групп захвата с положительным прогнозом go to @ JvdV , как он предложил со своим шаблоном в комментариях.

Как В качестве альтернативы вы можете получить номера / имена групп в порядке, указанном в расписании в вопросе, путем захвата цифр лестницы / этажа / двери и определения количества частей прямого sla sh, за которым следует di git находятся прямо справа.

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

^(?<address>(?<streetname>\h*\S.*?)\h*(?<housenumber>\d+\h*[A-Za-z]?))(?:/(?<stairs>\d+)(?=(?:/\d+){1,2}))?(?:/(?<floor>\d)(?=(?:/\d+)))?(?:/(?<door>\d+))?$

Regex demo | Php демонстрация

По частям

  • ^ Начало строки
  • (?<address> Группа адрес
    • (?<streetname> Группа название улицы
      • \h*\S.*? Сопоставьте 0+ горизонтальных пробельных символов, символ без пробелов, чтобы убедиться, что адрес не пуст и сопоставьте любой символ как можно меньше (не жадный)
    • ) Закрыть группу название улицы
    • \h* Сопоставить 0+ горизонтальных пробелов символы для конечных пробелов после названия улицы
    • (?<housenumber> Группа номер дома
      • \d+\h*[A-Za-z]? Соответствие 1+ цифр, 0+ горизонтальных пробельных символов и необязательный char a-zA -Z
    • ) Закрытая группа номер дома
  • ) Закрытая группа адрес
  • (?: Группа без захвата
    • /(?<stairs>\d+) Группа stairs, соответствие 1+ цифр
    • (?=(?:/\d+){1,2}) Положительный просмотр вперед, подтверждение того, что справа - 1 или 2 раза / с последующим 1 или 2 цифры
  • )? Закройте группу и сделайте ее необязательной
  • (?: Группа без захвата
    • /(?<floor>\d+) Группа этаж , соответствие 1+ цифр
    • (?=(?:/\d)) Положительный просмотр вперед, утверждение, что справа - /, за которым следует di git
  • )? Закройте группу и сделайте ее необязательной
  • (?: Группа без захвата
    • /(?<door>\d+) Группа дверь , совпадение 1+ цифр
  • )? Закройте группу и сделайте ее необязательной
  • $ Конец строки

Пример кода

$re = '~^(?<address>(?<streetname>\h*\S.*?)\h*(?<housenumber>\d+\h*[A-Za-z]?))(?:/(?<stairs>\d+)(?=(?:/\d+){1,2}))?(?:/(?<floor>\d)(?=(?:/\d+)))?(?:/(?<door>\d+))?$~m';
$strings = [
    "Lilienstr. 12a",
    "Leibnizstraße 36/28/2",
    "Prager Straße 14/3/1/4",
    "Guentherstr. 43 B",
    "Eberhard-Leibnitz Str. 1/7",
    "Schießstätte 7/7"
];

foreach ($strings as $string) {
    preg_match_all($re, $string, $matches, PREG_SET_ORDER);
    $address = array_filter($matches[0], "is_string", ARRAY_FILTER_USE_KEY); // from php 5.6
    print_r($address);
}

Выход

Array
(
    [address] => Lilienstr. 12a
    [streetname] => Lilienstr.
    [housenumber] => 12a
)
Array
(
    [address] => Leibnizstraße 36
    [streetname] => Leibnizstraße
    [housenumber] => 36
    [stairs] => 28
    [floor] => 
    [door] => 2
)
Array
(
    [address] => Prager Straße 14
    [streetname] => Prager Straße
    [housenumber] => 14
    [stairs] => 3
    [floor] => 1
    [door] => 4
)
Array
(
    [address] => Guentherstr. 43 B
    [streetname] => Guentherstr.
    [housenumber] => 43 B
)
Array
(
    [address] => Eberhard-Leibnitz Str. 1
    [streetname] => Eberhard-Leibnitz Str.
    [housenumber] => 1
    [stairs] => 
    [floor] => 
    [door] => 7
)
Array
(
    [address] => Schießstätte 7
    [streetname] => Schießstätte
    [housenumber] => 7
    [stairs] => 
    [floor] => 
    [door] => 7
)
1 голос
/ 05 августа 2020

Не зная австрийских форматов адресов, мне трудно сказать, правильно ли это, однако см. Регулярное выражение ниже.

^(.*)\s+(\d+(?:\s*[a-zA-Z])?)(?:\/(\d+))?(?:\/(\d+))?(?:\/(\d+))?\s*(?:$|\(|[A-Z]{2})

Это выражение всегда будет соответствовать всем 4 группам чисел (1/2 / 3/4), поэтому вам нужно будет выполнить дополнительную обработку, чтобы определить, есть ли в адресе номер дома, лестница, пол и дверь, по сравнению с тем, если в адресе есть только номер дома и дверь.

Например:

<?php

$pattern = '^(.*)\s+(\d+(?:\s*[a-zA-Z])?)(?:\/(\d+))?(?:\/(\d+))?(?:\/(\d+))?\s*(?:$|\(|[A-Z]{2})$';

$addresses = [
    'Lilienstr. 12a',
    'Leibnizstraße 36/28/2',
    'Prager Straße 14/3/1/4',
    'Guentherstr. 43 B',
    'Eberhard-Leibnitz Str. 1/7',
    'Schießstätte 7/7'
];

$results = [];

foreach ( $addresses as $address ) {
    
    // 0. Full match
    // 1. Streetname
    // 2. Housenumber
    // 3. Stairs
    // 4. Floor
    // 5. Door
    preg_match( '/' . $pattern . '/', $address, $matches );

    // Remove full match from 
    array_shift( $matches );
    
    // Set up default values
    $streetname = array_shift( $matches );
    $housenumber = null;
    $stairs = null;
    $floor = null;
    $door = null;

    // Count total values given
    $total = count( array_filter( array_map( 'trim', $matches ) ) );

    switch ( $total ) {

        // Has all 4 parts
        case 4:
            $housenumber = $matches[ 0 ];
            $stairs = $matches[ 1 ];
            $floor = $matches[ 2 ];
            $door = $matches[ 3 ];
            break;

        // Only has 3 parts
        case 3:
            $housenumber = $matches[ 0 ];
            $stairs = $matches[ 1 ];
            $door = $matches[ 2 ];
            break;

        // Only has 2 parts
        case 2:
            $housenumber = $matches[ 0 ];
            $door = $matches[ 1 ];
            break;

        // Has 1 part
        default:
            $housenumber = $matches[ 0 ];
            break;
    }

    // Add to results array
    $results[] = [
        'address' => $address,
        'streetname' => $streetname,
        'housenumber' => $housenumber,
        'stairs' => $stairs,
        'floor' => $floor,
        'door' => $door
    ];

}

print_r( $results );

Выход

Array
(
    [0] => Array
        (
            [address] => Lilienstr. 12a
            [streetname] => Lilienstr.
            [housenumber] => 12a
            [stairs] => 
            [floor] => 
            [door] => 
        )

    [1] => Array
        (
            [address] => Leibnizstraße 36/28/2
            [streetname] => Leibnizstraße
            [housenumber] => 36
            [stairs] => 28
            [floor] => 
            [door] => 2
        )

    [2] => Array
        (
            [address] => Prager Straße 14/3/1/4
            [streetname] => Prager Straße
            [housenumber] => 14
            [stairs] => 3
            [floor] => 1
            [door] => 4
        )

    [3] => Array
        (
            [address] => Guentherstr. 43 B
            [streetname] => Guentherstr.
            [housenumber] => 43 B
            [stairs] => 
            [floor] => 
            [door] => 
        )

    [4] => Array
        (
            [address] => Eberhard-Leibnitz Str. 1/7
            [streetname] => Eberhard-Leibnitz Str.
            [housenumber] => 1
            [stairs] => 
            [floor] => 
            [door] => 7
        )

    [5] => Array
        (
            [address] => Schießstätte 7/7
            [streetname] => Schießstätte
            [housenumber] => 7
            [stairs] => 
            [floor] => 
            [door] => 7
        )

)

См. Здесь: http://sandbox.onlinephpfunctions.com/code/3952b2f3cab251e7137bcd9d55e42d8c8bcdd723

0 голосов
/ 05 августа 2020

Это то, что вы ищете:

([a-zA-Z][ \-0-9a-zA-ZäöüÄÖÜß.\/]+\w)\s*\|\s+(\d+(?:\s?[a-zA-Z])?)\s*\|\s+(\d+)?\s*\|\s+(\d+)?\s*\|\s+(\d+)?

Пожалуйста, проверьте демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...