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.
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
Możesz przetestować swoje wyrażenie online: http://www.gskinner.com/RegExr/ – twk
'/^[a-zA-Z0-9] + ([a-zA-Z0-9] (_ | - |) [a-zA-Z0-9]) * [a-zA-Z0-9] * $/'wystarczy. Nie trzeba dodawać '+' na końcu –