2017-08-22 4 views
2

Ich benutze diese PHP regexp um zu überprüfen, ob ein Feld einen Namen enthält, bestehend aus mindestens einem Vor-/Nachnamen, und dann optionale andere Vornamen oder Initialen.preg_match Vorname/Nachname übereinstimmende Gruppen

$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]; 

Scheint gut in Bezug auf Treffer/Fehlschläge, d. H. Wahr/falsch, ob es übereinstimmt oder nicht.

Aber dann die Vor- und Nachnamen mit Gruppen Ich versuche, die gleiche Sache zu verwenden, zu extrahieren, die ich bin zu kämpfen Recht zu bekommen ..

Holen Sie sich viele Ergebnisse wie:

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

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

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

..aber was ich wirklich will, ist für eines der 'Übereinstimmungen' immer nur den Vornamen zu enthalten, und einen, der immer nur den Nachnamen enthält.

Irgendwelche Hinweise, was falsch ist?

Antwort

1

Jedes Mal, wenn Sie definieren ein capturing group in einem regulären Ausdruck, der Teil der Zeichenfolge als separates Element in dem resultierenden Array wird sie paßt hinzugefügt. Es gibt zwei Strategien, um sie loszuwerden:

  • das Muster optimieren und loszuwerden der redundanten Gruppen (zB Gruppen um einzelne Atome - (a)+ =>a+)
  • Schalten einfangenden Gruppen in non-capturing ((\s+\w+)+ =>(?:\s+\w+)+)

auch in Ihrem Fall, können Sie das prasseln verbessern, wenn Sie die Buchstaben ersetzen mit der \p{L} Unicode Festigkeitsklasse passenden Teil, der alle Buchstaben übereinstimmt.

Verwenden

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

Siehe regex demo

Hier wird nur eine Gruppierung links, (?:...), und es ist optional, die ?, nachdem sie es 1 oder 0 mal macht übereinstimmen.

Einzelheiten

  • [\p{L}'-]{2,} - 2 oder mehr Buchstaben, ' oder -
  • (?:\s[\p{L}'-]+)?-1 oder 0 Vorkommen von einem Leerzeichen und dann 1 oder mehr Buchstaben, ' oder -
  • \s - ein Leerzeichen
  • [\p{L}'-]{2,} - 2 oder mehr Buchstaben, ' oder -
1

Versuchen:

(?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,}) 

Haupt Fehler Sie haben wiederholte erste Gruppe {2,} - nicht der erste Bereich

1

Verwendung nicht-einfangenden Gruppen (?:...), wenn Sie Klammern verwenden, aber Sie tun nicht möchte diesen Teil (z. B. Teil von Leerzeichen und zweiter Vorname) zuordnen und einen Quantifizierer in die Erfassungsgruppe einfügen, nicht nur die Zeichen, die übereinstimmen (z. B. für Vorname {2,} sollte in Erfassungsgruppe sein).

([\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,})