preg_match группы соответствия имени / фамилии

Я использую это регулярное выражение PHP, чтобы проверить true / false, содержит ли поле имя, состоящее как минимум из имени / фамилии, а затем, необязательно, других отчеств или инициалов.

$success = preg_match("/([\x{00c0}-\x{01ff}a-zA-Z'-]){2,}(\s([\x{00c0}-\x{01ff}a-zA-Z'-]{1,})*)?\s([\x{00c0}-\x{01ff}a-zA-Z'-]{2,})/ui",$user['name'],$matches);

$output[($success ? 'hits' : 'misses')][] = ['id' => $user['id'],'email' => $user['email'],'name' => $user['name'],'matches' => $matches];

Кажется, работает хорошо с точки зрения попаданий / промахов, то есть истина / ложь, независимо от того, совпадает или нет.

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

Получить много результатов, таких как:

  "name": "Jonny Nott",
"matches": [
"Jonny Nott",
"y",
"",
"",
"Nott"]

"name": "Name Here",
"matches": [
"Name Here",
"e",
"",
"",
"Here"]

"matches": [
"Jonathan M Notty",
"n",
" M",
"M",
"Notty"]

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

Любые указатели относительно того, что не так?

2

Решение

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

  • Оптимизируйте схему и избавьтесь от избыточных групп (например, групп вокруг отдельных атомов — (a)+ => a+)
  • Превратите группы захвата в без захвата ((\s+\w+)+ => (?:\s+\w+)+)

Кроме того, в вашем случае вы можете улучшить шаблон, если вы замените часть, соответствующую букве, на \p{L} Класс свойств Unicode, который соответствует любым буквам.

использование

/[\p{L}'-]{2,}(?:\s[\p{L}'-]+)?\s[\p{L}'-]{2,}/u

Увидеть regex demo

Здесь осталась только одна группировка, (?:...)и это необязательно, ? после того, как это делает это соответствует 1 или 0 раз.

подробности

  • [\p{L}'-]{2,} — 2 или более букв, ' или же -
  • (?:\s[\p{L}'-]+)? — 1 или 0 вхождений пробела, а затем 1 или более букв, ' или же -
  • \s — пробел
  • [\p{L}'-]{2,} — 2 или более букв, ' или же -
1

Другие решения

Пытаться:

(?P<firstName>[\x{00c0}-\x{01ff}a-zA-Z'-]{2,})(\s([\x{00c0}-\x{01ff}a-zA-Z'-]{1,})*)?\s(?P<lastName>[\x{00c0}-\x{01ff}a-zA-Z'-]{2,})

Главная ошибка, которую вы повторили, первая группа {2,} — не первый диапазон

1

Используйте группы без захвата (?:...) всякий раз, когда вам нужно использовать круглые скобки, но вы не хотите сопоставлять эту часть (например, часть пробелов и отчество) и включать квантификатор в группу захвата, а не только символы для сопоставления (например, для имени {2,} должен быть в группе захвата).

([\x{00c0}-\x{01ff}a-zA-Z'-]{2,})(?:\s(?:[\x{00c0}-\x{01ff}a-zA-Z'-]{1,})*)?\s([\x{00c0}-\x{01ff}a-zA-Z'-]{2,})
1
По вопросам рекламы [email protected]