2011-05-11 9 views
11

Okay, czytałem o regex cały dzień teraz i nadal nie rozumiem tego poprawnie. Próbuję sprawdzić nazwę, ale funkcje, które mogę znaleźć w Internecie, używają tylko [a-zA-Z], pozostawiając znaki, które muszę zaakceptować.Regex dla nazw ze znakami specjalnymi (Unicode)

Po prostu potrzebuję wyrażenia regularnego, które sprawdza, czy nazwa zawiera co najmniej dwa słowa, i że nie zawiera liczb ani znaków specjalnych, takich jak !"#¤%&/()=..., jednak słowa mogą zawierać znaki takie jak æ, é, Â itd. .

przykładem przyjętą nazwą będzie „John Elkjærd” lub „Andre Svenson”
niezgłoszeniowe przyjętą nazwą będzie „Hans” „H nn Andersen” lub "Martin Henriksen !"

Jeśli jest to ważne, używam strony klienta funkcji javascript .match() i chcę używać tylko "negatywnej" strony serwera php: preg_replace(). (usuwanie niepasujących znaków).

Każda pomoc będzie mile widziana.

Aktualizacja:
Ok, dzięki Alix Axel's answer mam ważną rolę w dół, z boku jeden serwer.

Ale jak sugeruje strona z LightWing's answer, nie mogę znaleźć nic na temat obsługi Unicode dla javascript, więc skończyłem z pół rozwiązaniem dla klienta, po prostu sprawdzając co najmniej dwa słowa i minimum 5 znaków takich jak to:

if(name.match(/\S+/g).length >= minWords && name.length >= 5) { 
    //valid 
} 

alternatywą byłoby określić wszystkie znaki unicode, jak sugerowano w shifty's answer, które może skończyć się robi coś takiego, wraz z powyższego rozwiązania, ale to jest trochę niepraktyczny chociaż.

+0

można opracować je np –

+0

@ Amit Gupta, dzięki, zrobiłem. :) –

Odpowiedz

29

Spróbuj następujące wyrażenia regularnego:

^(?:[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+\s[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+\s?)+$ 

W PHP to przekłada się na:

if (preg_match('~^(?:[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+\s[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+\s?)+$~u', $name) > 0) 
{ 
    // valid 
} 

Należy ją czytać tak:

^ # start of subject 
    (?:  # match this: 
     [   # match a: 
      \p{L}  # Unicode letter, or 
      \p{Mn}  # Unicode accents, or 
      \p{Pd}  # Unicode hyphens, or 
      \'   # single quote, or 
      \x{2019} # single quote (alternative) 
     ]+    # one or more times 
     \s   # any kind of space 
     [    #match a: 
      \p{L}  # Unicode letter, or 
      \p{Mn}  # Unicode accents, or 
      \p{Pd}  # Unicode hyphens, or 
      \'   # single quote, or 
      \x{2019} # single quote (alternative) 
     ]+    # one or more times 
     \s?   # any kind of space (0 or more times) 
    )+  # one or more times 
$ # end of subject 

szczerze don nie wiem jak to przenieść do JavaScript CRIPT, nie jestem nawet pewien obsługuje JavaScript właściwości Unicode, ale w PHP PCRE to seems to work flawlessly @ IDEOne.com:

$names = array 
(
    'Alix', 
    'André Svenson', 
    'H4nn3 Andersen', 
    'Hans', 
    'John Elkjærd', 
    'Kristoffer la Cour', 
    'Marco d\'Almeida', 
    'Martin Henriksen!', 
); 

foreach ($names as $name) 
{ 
    echo sprintf('%s is %s' . "\n", $name, (preg_match('~^(?:[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+\s[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+\s?)+$~u', $name) > 0) ? 'valid' : 'invalid'); 
} 

przykro mi, że nie może pomóc czasowo część Javascript ale chyba ktoś tu będzie.


Sprawdza:

  • John Elkjærd
  • André Svenson
  • Marco D'Almeida
  • Kristoffer la Cour

Inva lidates:

  • Hans
  • H4nn3 Andersen
  • Martin Henriksen!

Aby zastąpić nieprawidłowe znaki, choć nie jestem pewien, dlaczego trzeba to po prostu trzeba go zmienić nieznacznie:

$name = preg_replace('~[^\p{L}\p{Mn}\p{Pd}\'\x{2019}\s]~u', '$1', $name); 

Przykłady:

  • H4nn3 Andersena -> Hnn Andersen
  • Martin Henriksen! -> Martin Henriksen

Pamiętaj, że zawsze trzeba użyć modyfikatora u.

+0

Dzięki za odpowiedź, to jest idealne! Muszę tylko sprawić, żeby działało z js teraz, ale nie może być trudne, teraz przynajmniej mam coś od czego zacząć. :) Ohh, a powodem, dla którego chcę usunąć nieprawidłowe znaki, jest uniknięcie czegoś takiego jak "Tamperdata" lub "cURL", aby dać mi błędne dane wejściowe, ale jeśli sprawdzę również, nie ma to znaczenia :) Jeszcze raz dziękuję. –

+0

@Kristoffer: Zaktualizowałem moje pytanie, aby lepiej wyjaśnić wyrażenie regularne, jeśli żadna inna alternatywa JS nie przedstawia, że ​​zawsze możesz użyć Ajax i wywołać PHP w celu sprawdzenia poprawności. –

+0

wyjaśnienie części regex jest wspaniałe, daje mi coś więcej niż tylko ślepą kopię-wklej, aby przejść do. JS nadal sprawia mi kłopoty, ale kiedy/jeśli znajdę rozwiązanie, opublikuję go tutaj. –

2

można dodać dozwolonych specjalne znaki na regex.

przykład:

[a-zA-ZßöäüÖÄÜæé]+ 

EDIT:

nie jest najlepszym rozwiązaniem, ale to dałoby wynik jeśli istnieją co najmniej słów.

[a-zA-ZßöäüÖÄÜæé]+\s[a-zA-ZßöäüÖÄÜæé]+ 
+1

Dlaczego '[\ t]' a nie tylko '\ s'? –

+0

Nie, niezupełnie, ale opcja, i tak dziękuję. :) –

+2

@Alis: \ s jest lepsze. dzięki za radę. Nie jestem regexpertem: D – superbly

0

Podczas sprawdzania ciąg wejściowy można

  • trim(), aby usunąć prowadząc/końcowe spacje
  • mecz przeciwko [^ \ w \ s], aby wykryć non-Word \ znaki nie-białych
  • dopasuj do \ s +, aby uzyskać liczbę separatorów wyrazów równą liczbie słów + 1.

Jednak nie jestem pewien, czy skrót skraca znaki akcentowane, ale powinien należeć do kategorii "znaków słownych".

+0

'\ w' jest równoważne' [0-9a-zA-Z_] ', w zależności od specyficznych ustawień narodowych maszyny może to (nie) działać ze znakami akcentowanymi/unicode, tak czy inaczej zawsze będzie pasować do cyfr, a nie powinno" t. –

+0

oh, wygląda na to, że będę musiał naprawić wiele fragmentów mojego własnego kodu wtedy :(thx za cenne informacje! – ashein

2

Jeśli chodzi o JavaScript, jest to trudniejsze, ponieważ składnia języka JavaScript Regex nie obsługuje właściwości znaku Unicode. Pragmatyczne rozwiązaniem byłoby dopasować litery tak:

[a-zA-Z\xC0-\uFFFF] 

Pozwala litery we wszystkich językach i cyfr nie obejmuje wszystkich i specjalnych (non-literowych) znaków powszechnie spotykane na klawiszach. Jest niedoskonały, ponieważ pozwala również na specjalne symbole Unicode, które nie są literami, np. emotikony, bałwanek i tak dalej. Jednakże, ponieważ symbole te zazwyczaj nie są dostępne na klawiaturach, nie sądzę, że zostaną one wprowadzone przez przypadek. Tak więc w zależności od wymagań może to być dopuszczalne rozwiązanie.

+0

Dzięki. Szukałem tego, ponieważ RegEx powyżej nie działa po stronie klienta sprawdzanie poprawności JavaScript ... I zakończyło się tym: public const string NameFull = @ "^ (?!. {52,}) [a-zA-Z \ xC0- \ uFFFF \. \ '\ -] {2,50} (?: [a -zA-Z \ xC0- \ uFFFF \. \ '\ -] {2,50}) + $ "i następnie zatwierdza emotikony: https://regex101.com/r/jP5jC5/2 – Yovav

2

Oto optymalizacja nad fantastyczną odpowiedzią @Alix powyżej. Usuwa potrzebę dwukrotnego zdefiniowania klasy znaków i pozwala na łatwiejsze zdefiniowanie dowolnej liczby wymaganych słów.

^(?:[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+(?:$|\s+)){2,}$ 

To można podzielić w następujący sposób:

^   # start 
    (?:  # non-capturing group 
    [   # match a: 
     \p{L}  # Unicode letter, or 
     \p{Mn} # Unicode accents, or 
     \p{Pd} # Unicode hyphens, or 
     \'  # single quote, or 
     \x{2019} # single quote (alternative) 
    ]+  # one or more times 
    (?:  # non-capturing group 
     $   # either end-of-string 
    |   # or 
     \s+  # one or more spaces 
    )   # end of group 
){2,}  # two or more times 
$   # end-of-string 

Zasadniczo, to mówi się znaleźć słowo zdefiniowane przez klasę postaci, a następnie albo znaleźć jeden lub więcej spacji lub końca linia. Na końcu {2,} mówi, że aby mecz zakończył się sukcesem, należy znaleźć co najmniej dwa słowa. To gwarantuje, że przykład "Hans" OP nie będzie pasował.


Wreszcie, ponieważ znalazłem na to pytanie, patrząc na podobne rozwiązanie dla , tu jest wyrażenie regularne, ponieważ może być stosowany w Ruby 1.9+

\A(?:[\p{L}\p{Mn}\p{Pd}\'\U+2019]+(?:\Z|\s+)){2,}\Z 

Główne zmiany są za pomocą \ a i \ Z dla początku i końca łańcucha (zamiast linii) i notacji znaków Unicode Rubiego.

0

To regex JS że używam do fantazyjnych nazwach składających się z maksymalnie 3 słowa (od 1 do 60 znaków), oddzielone spacją/apostrof/minus

^([a-zA-Z\xC0-\uFFFF]{1,60}[ \-\']{0,1}){1,3}$ 
Powiązane problemy