2009-08-03 17 views
29

Questo sembra corrispondere alle regole che ho definito, ma sto solo iniziando a imparare regex stasera, quindi mi chiedo se sia corretto.Come convalidare un nome utente con regex?

Regole:

  • nomi utente può essere costituito da minuscole e capitali
  • nomi utente può consistere in alfanumerico personaggi
  • nomi utente possono consistere di sottolineatura e trattini e spazi
  • non possono essere due sottolineature , due hypens o due spazi consecutivi
  • Latta Non hanno una sottolineatura, hypen o spazio all'inizio o alla fine

modello Regex:

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

Ciò non consentirà alcun carattere non latino in nomi utente. Se vuoi essere in grado di gestire caratteri non latini, dovresti usare una classe di caratteri incorporata invece di definire esplicitamente quali caratteri sono lettere e numeri. – Welbog

+2

Puoi testare la tua espressione online: http://www.gskinner.com/RegExr/ – twk

+0

'/^[a-zA-Z0-9] + ([a-zA-Z0-9] (_ | - |) [a-zA-Z0-9]) * [a-zA-Z0-9] * $/'è sufficiente. Non c'è bisogno di aggiungere '+' all'ultimo –

risposta

53

Le specifiche della domanda non sono molto chiare, quindi suppongo che la stringa possa contenere solo lettere e cifre ASCII, con trattini, caratteri di sottolineatura e spazi come separatori interni. La carne del problema sta nell'assicurare che il primo e l'ultimo carattere non sono separatori, e che non c'è mai più di un separatore consecutivo (quella parte sembra comunque chiara). Ecco il modo più semplice:

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

Dopo aver fatto corrispondere uno o più caratteri alfanumerici, se c'è un separatore che deve essere seguita da uno o più caratteri alfanumerici; ripetere se necessario.

Diamo un'occhiata alle espressioni regolari di alcune delle altre risposte.

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

Questa è effettivamente la stessa (supponendo che il sapore regex supporta lo standard POSIX classe caratteri notazione), ma perché fare il separatore opzionale? L'unica ragione per cui ti trovi in ​​quella parte della regex, in primo luogo, è se c'è un separatore o qualche altro carattere non valido.

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

D'altra parte, questo funziona solo perché il separatore è opzionale. Dopo il primo separatore, può corrispondere solo a un alfanumerico alla volta. Per abbinare di più, deve continuare a ripetere l'intero gruppo: zero separatori seguiti da uno alfanumerico, più e più volte. Se il secondo [a-zA-Z0-9] è stato seguito da un segno più, potrebbe trovare una corrispondenza con un percorso molto più diretto.

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

Questo utilizza lookbehind illimitata, che è una caratteristica molto rara, ma è possibile utilizzare un lookahead nello stesso senso:

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

Questo esegue essenzialmente una ricerca separata per due separatori consecutivi, e fallisce la partita se ne trova una. Il corpo principale deve quindi solo assicurarsi che tutti i caratteri siano alfanumerici o separatori, con il primo e l'ultimo essere alfanumerici. Poiché questi due sono obbligatori, il nome deve essere lungo almeno due caratteri.

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

Questo è il tuo regex, e richiede la stringa per iniziare e terminare con due caratteri alfanumerici, e se ci sono due separatori all'interno della stringa, ci devono essere esattamente due caratteri alfanumerici tra di loro. Quindi ab, ab-cd e ab-cd-ef corrisponderanno, ma a, a-b e a-b-c no.

Inoltre, come alcuni dei commentatori hanno sottolineato, il (_|-|) nella vostra regex dovrebbe essere [-_ ]. Questa parte non è errata, ma se hai una scelta tra un'alternativa e una classe di personaggio, dovresti sempre andare con la classe di caratteri: sono più efficienti e più leggibili.

Ancora una volta, non sono preoccupato se "alfanumerico" debba includere caratteri non ASCII o il significato esatto di "spazio", solo come applicare una politica di separatori interni non contigui con un'espressione regolare.

+0

ok, e come limitare questo? qualcosa come: ^ ([a-zA-Z0-9] + ([a-zA-Z0-9] (_ | - |) [a-zA-Z0-9]) * [a-zA-Z0- 9] +) {6,25} $ –

+0

@GabrielAnderson: vuoi dire che l'intero nome (compresi i separatori) deve avere almeno 6 e al massimo 25 caratteri? Ciò richiede un lookahead. Basta aggiungere '(? =. {6,25} $)' all'inizio, subito dopo l'ancora ('^'). –

3

Suggerisco di scrivere alcuni test di unità di mettere il Regex attraverso passi. Ciò aiuterà anche alcuni mesi a partire da ora quando si riscontra un problema con il Regex e occorre aggiornarlo.

+2

+1. È sicuramente una buona idea coprire le regex con diversi test unitari –

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

è uno 0 o più repetitone di alfanum, dashspace, alfanum.

Quindi sarebbe abbinare

a_aa_aa_a 

ma non

aaaaa 

Anche l'espressione regolare completa non può corrispondere

a_aaaaaaaaa_a for example. 

Guardiamo indietro a ciò che si vuole:

* 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 

L'inizio è semplice ... basta abbinare un alfanum, quindi (ingaggiando i due nella regola della riga) un (alphanum o dashspace) * e al e un alfan di nuovo.

Per evitare i due dashspaces in una riga è probabilmente necessario capire lookahead/lookbehind.

Oh, e per quanto riguarda l'altra risposta: Si prega di scaricare Espresso, ti aiuta VERAMENTE a capire meglio queste cose.

+2

dare a un uomo un pesce o insegnare a un uomo a pescare ...? È un dilemma –

+1

Facile: dai a un uomo un pesce * mentre * gli insegni a pescare. :) –

+1

Mostra a un uomo come pescare catturando un pesce per dimostrare che i tuoi metodi funzionano? – Kzqai

2
  1. alfanumerico non è solo [a-zA-Z0-9], è accentata, cirillico, greco e altre lettere, che possono essere utilizzati nel nome utente.

  2. (_|-|) possono essere sostituiti per classe [-_ ] carattere

+4

'[_-]' è "tutto tra underscore e spazio". Si desidera avere prima il trattino per farlo interpretare correttamente: '[-_]' – Welbog

0

Un'altra raccomandazione per Expresso 3.0 qui - molto facile da usare e costruire le stringhe con.

0

La tua espressione regolare non funziona. La parte difficile è il controllo per spazi/trattini consecutivi.È possibile utilizzare questo, che utilizza look-dietro:

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

Questo non funzionerà nella maggior parte dei motori regexp perché la stringa look-behind non è una lunghezza fissa. – mikej

+0

Sono rovinato dal motore regex .NET :) –

+0

Sì, volevo dire nel mio commento che il motore .NET è uno di una manciata dove * funzionerà * :-) – mikej

0

Con gli sguardi di esso, che regola non corrisponde a qualcosa come "a_bc", "ab_c", "a_b" o "a_b_c".

Prova: /^[a-zA-Z0-9]+([_\s\-]?[a-zA-Z0-9])*$/ che corrisponde ai casi precedenti ma non una combinazione di spazi, trattini o caratteri di sottolineatura uno accanto all'altro. Ad esempio: "_-" o "_" non sono consentiti.

1

Utilizzando la classe di caratteri POSIX per i caratteri alfanumerici per farlo funzionare per i caratteri accentati e altri stranieri alfabetici:

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

più efficienti (previene Cattura):

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

Questi anche prevenire sequenze di più di uno spazio/trattino/trattino basso in combinazione. Non segue le vostre specifiche se ciò sia desiderabile, ma la vostra espressione regolare sembra indicare che questo è ciò che volete.

12

È espressione regolare può essere semplificata:

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

visualizzate con Regexper:

Visualization of username validation regex.

Come si può vedere un nome utente deve sempre iniziare con un carattere alfanumerico. I caratteri speciali (_, , -) devono essere seguiti da un carattere alfanumerico. L'ultimo carattere deve essere un carattere alfanumerico.