Кредиты для ядра шаблона с использованием дополнительных групп захвата с положительным прогнозом 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
)