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.
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
Puoi testare la tua espressione online: http://www.gskinner.com/RegExr/ – twk
'/^[a-zA-Z0-9] + ([a-zA-Z0-9] (_ | - |) [a-zA-Z0-9]) * [a-zA-Z0-9] * $/'è sufficiente. Non c'è bisogno di aggiungere '+' all'ultimo –