2009-08-03 24 views
29

To wydaje się pasować do reguł, które zdefiniowałem, ale dopiero zaczynam uczyć się regex dziś wieczorem, więc zastanawiam się, czy to jest poprawne.Jak sprawdzić nazwę użytkownika za pomocą wyrażenia regularnego?

Zasady:

  • Nazwy użytkowników mogą składać się z małych liter i stolicach
  • Nazwy użytkownika może składać się ze znaków alfanumerycznych znaków
  • Nazwy użytkowników mogą składać się z podkreślenia i myślniki i spacje
  • nie może być dwóch podkreśleń , dwa hipers lub dwie spacje z rzędu
  • Can nie mają podkreślenia hypen lub przestrzeń na początku lub na końcu

Regex wzoru:

/^[a-zA-Z0-9]+([a-zA-Z0-9](_|-|)[a-zA-Z0-9])*[a-zA-Z0-9]+$/ 
+4

To nie zezwoli na używanie znaków spoza alfabetu łacińskiego w nazwach użytkowników. Jeśli chcesz obsługiwać znaki spoza alfabetu łacińskiego, powinieneś użyć wbudowanej klasy znaków zamiast jawnie określać, które znaki są literami i cyframi. – Welbog

+2

Możesz przetestować swoje wyrażenie online: http://www.gskinner.com/RegExr/ – twk

+0

'/^[a-zA-Z0-9] + ([a-zA-Z0-9] (_ | - |) [a-zA-Z0-9]) * [a-zA-Z0-9] * $/'wystarczy. Nie trzeba dodawać '+' na końcu –

Odpowiedz

53

Specyfikacje w pytaniu nie są bardzo jasne, więc po prostu przyjmuję, że ciąg może zawierać tylko litery i cyfry ASCII, z łącznikami, podkreśleniami i spacjami jako separatorami wewnętrznymi. Mięso problemu polega na tym, że pierwszy i ostatni znak nie są separatorami i że nigdy nie ma więcej niż jednego separatora z rzędu (ta część wydaje się jasna, tak czy inaczej). Oto najprostszy sposób:

/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/ 

Po dopasowaniu jeden lub więcej znaków alfanumerycznych, jeśli Jest to separator musi nastąpić jeden lub więcej znaków alfanumerycznych; powtórz w razie potrzeby.

Spójrzmy na wyrażeń regularnych z niektórych innych odpowiedzi.

/^[[:alnum:]]+(?:[-_ ]?[[:alnum:]]+)*$/ 

ta jest skutecznie takie same (zakładając, że smak regex wspiera charakter klasy notacji POSIX), ale dlaczego uczynić separator opcja? Jedynym powodem, dla którego będziesz w tej części wyrażeń regularnych, jest to, że istnieje separator lub inna, nieważna postać.

/^[a-zA-Z0-9]+([_\s\-]?[a-zA-Z0-9])*$/ 

Z drugiej strony, to działa tylko ponieważ separator jest opcjonalny. Po pierwszym separatorze może dopasować tylko jeden alfanumeryczny na raz. Aby dopasować więcej, musi powtarzać całą grupę: separatory zerowe, po których następuje jeden alfanumeryczny, w kółko. Jeśli po drugim znaku [a-zA-Z0-9] pojawi się znak plus, może on znaleźć dopasowanie przez znacznie bardziej bezpośrednią trasę.

/^[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9](?<![_\s\-]{2,}.*)$/ 

ta wykorzystuje nieograniczoną lookbehind, która jest bardzo rzadka cecha, ale można użyć uprzedzona do tego samego efektu:

/^(?!.*[_\s-]{2,})[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9]$/ 

ten wykonuje zasadniczo odrębny poszukiwania dwóch kolejnych separatorów, a nie mecz, jeśli go znajdzie. Główny korpus musi tylko upewnić się, że wszystkie znaki są alfanumeryczne lub separatory, przy czym pierwszy i ostatni jest alfanumeryczny. Ponieważ te dwie są wymagane, nazwa musi składać się z co najmniej dwóch znaków.

/^[a-zA-Z0-9]+([a-zA-Z0-9](_|-|)[a-zA-Z0-9])*[a-zA-Z0-9]+$/ 

To jest twój własny regex, a to wymaga ciąg, aby rozpocząć i zakończyć z dwóch znaków alfanumerycznych, a jeśli istnieją dwa separatory w ciągu, nie muszą być dokładnie dwa alfanumeryczne między nimi. Tak więc ab, ab-cd i ab-cd-ef będzie pasować, ale nie będzie.

Ponadto niektórzy komentatorzy wskazali, że (_|-|) w swoim regexie powinno być [-_ ]. Ta część nie jest niepoprawna, ale jeśli masz wybór między naprzemiennym a klasą postaci, zawsze powinieneś iść z klasą znaków: są one bardziej wydajne, a także bardziej czytelne.

Jeszcze raz nie martwię się, czy "alfanumeryczne" ma zawierać znaki spoza ASCII, czy dokładne znaczenie "przestrzeni", jak wymusić politykę nieciągłych wewnętrznych separatorów za pomocą wyrażenia regularnego.

+0

ok, i jak to ograniczyć? coś w stylu: ^ ([a-zA-Z0-9] + ([a-zA-Z0-9] (_ | - |) [a-zA-Z0-9]) * [a-zA-Z0- 9] +) {6,25} $ –

+0

@GabrielAnderson: Masz na myśli, że cała nazwa (łącznie z separatorami) musi mieć co najmniej 6 i maksymalnie 25 znaków? To wymaga uprzedzenia. Po prostu dodaj '(? =. {6,25} $)' na początku, zaraz za kotwicą ('^'). –

3

Proponuję pisanie kilka testów jednostkowych umieścić regex poprzez jego kroków. Pomoże to również za kilka miesięcy, kiedy znajdziesz problem z Regeksem i musisz go zaktualizować.

+2

+1. Z pewnością dobrym pomysłem jest objęcie regexa kilkoma testami jednostkowymi: –

4
([a-zA-Z0-9](_|-|)[a-zA-Z0-9])* 

jest 0 lub więcej repetiton z ALPHANUM, dashspace, ALPHANUM.

Tak byłoby dopasować

a_aa_aa_a 

ale nie

aaaaa 

Kompletny regexp nie może się równać

a_aaaaaaaaa_a for example. 

Spójrzmy wstecz na to, co chcesz:

* Usernames can consist of lowercase and capitals or alphanumerica characters 
* Usernames can consist of alphanumeric characters 
* Usernames can consist of underscore and hyphens and spaces 
* Cannot be two underscores, two hypens or two spaces in a row 
* Cannot have a underscore, hypen or space at the start or end 

Początek jest prosty ... wystarczy dopasować alfanum, a następnie (w oparciu o dwie reguły w rzędzie) an (alfanum lub dashspace) * i ponownie w alfanumie.

Aby zapobiec dwóm obszarom nawigacyjnym z rzędu, prawdopodobnie musisz zrozumieć poprzedni/lookbehind.

Aha, w odniesieniu do drugiej odpowiedzi: Proszę pobrać Espresso, NAPRAWDĘ pomaga ci pozbyć się tych rzeczy.

+2

dać mężczyźnie rybę, czy nauczyć człowieka łowić ryby ...? To dylemat –

+1

Łatwo: daj człowiekowi rybę * podczas gdy * nauczysz go łowić. :) –

+1

Pokaż mężczyźnie, jak łowić ryby, aby samemu udowodnić, że Twoje metody działają? – Kzqai

2
  1. alfanumerycznych nie tylko [a-zA-Z0-9], to akcentowane, cyrylicy, greki i innych listów, które mogą być użyte w nazwie użytkownika.

  2. (_|-|) może być zastąpiony przez klasy [-_ ] znaków

+4

'[_-]' to "wszystko między podkreśleniem a spacją". Chcesz najpierw wstawić łącznik, aby został poprawnie zinterpretowany: '[-_]' – Welbog

0

Kolejna rekomendacja dla Expresso 3.0 tutaj - bardzo łatwy w użyciu i budować struny.

0

Twoje polecenie regularne nie działa. Najtrudniejszą częścią jest sprawdzenie kolejnych spacji/myślników.Można używać ten jeden, który korzysta look-tył:

/^[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9](?<![_\s\-]{2,}.*)$/ 
+0

To nie zadziała w większości silników regexp, ponieważ ciąg znaków nie ma ustalonej długości. – mikej

+0

Jestem zepsuty przez silnik .NET regex :) –

+0

Tak, zamierzałem wspomnieć w moim komentarzu, że silnik .NET jest jedną z niewielu gdzie to * działa * :-) – mikej

0

przez wygląda na to, że reguła nie pasuje coś w stylu „a_bc”, „ab_c”, „a_b” lub „a_b_c”.

Spróbuj: /^[a-zA-Z0-9]+([_\s\-]?[a-zA-Z0-9])*$/ , które pasuje do powyższych przypadków, ale nie zawiera kombinacji spacji, myślników lub podkreśleń obok siebie. Np .: "_-" lub "_" są niedozwolone.

1

Korzystanie z klasy znaków POSIX dla znaków alfanumerycznych, aby pracować dla akcentowanych i innych obcych alfabetach:

/^[[:alnum:]]+([-_ ]?[[:alnum:]])*$/ 

bardziej wydajne (zapobiega przechwytuje):

/^[[:alnum:]]+(?:[-_ ]?[[:alnum:]]+)*$/ 

sekwencje te również zapobiegać tworzeniu więcej niż jedno spacja/łącznik/podkreślenie w połączeniu. Nie wynika to z Twojej specyfikacji, czy jest to pożądane, ale twoje własne wyrażenie wydaje się wskazywać, że właśnie tego chcesz.

12

Ty wyrażenie regularne można uprościć do:

/^[a-zA-Z0-9]+([_ -]?[a-zA-Z0-9])*$/ 

wizualizowane z Regexper:

Visualization of username validation regex.

Jak widać nazwa użytkownika ma zawsze zaczynają się od znaku alfanumerycznego. Znaki specjalne (_, , -) muszą być poprzedzone znakiem alfanumerycznym. Ostatni znak musi być alfanumeryczny.

Powiązane problemy