Como validar um nome de usuário com regex?

Isso parece coincidir com as regras que defini, mas só começando a aprender regex hoje, então estou me perguntando se está correto.

Regras:

  • Os nomes de usuários podem consistir em letras minúsculas e maiúsculas
  • Os nomes de usuários podem consistir em caracteres alfanuméricos
  • Os nomes de usuários podem consistir em sublinhados e hífens e espaços
  • Não pode ser dois sublinhados, dois hipensos ou dois espaços seguidos
  • Não pode ter um sublinhado, hypen ou espaço no início ou no final

Padrão de regex:

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

As especificações da questão não são muito claras, então, presumo que a string só pode conter letras e dígitos ASCII, com hifens, sublinhados e espaços como separadores internos. A carne do problema é garantir que o primeiro e o último caractere não sejam separadores, e que nunca haja mais de um separador em seguida (essa parte parece clara, pelo menos). Aqui está a maneira mais simples:

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

Depois de combinar um ou mais caracteres alfanuméricos, se houver um separador, ele deve ser seguido por um ou mais alfanuméricos; repita conforme necessário.

Vejamos regexes de algumas das outras respostas.

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

Isto é efetivamente o mesmo (assumindo que o seu sabor de regex suporta a notação de class de caracteres POSIX), mas por que tornar o separador opcional? A única razão pela qual você estaria nessa parte da regex, em primeiro lugar, é se há um separador ou algum outro caractere inválido.

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

Por outro lado, isso só funciona porque o separador é opcional. Após o primeiro separador, ele só pode corresponder a um alfanumérico de cada vez. Para combinar mais, ele deve continuar repetindo todo o grupo: separadores zero seguidos por um alfanumérico, repetidamente. Se o segundo [a-zA-Z0-9] fosse seguido por um sinal de mais, ele poderia encontrar uma correspondência por uma rota muito mais direta.

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

Isso usa lookbehind ilimitado, que é um recurso muito raro, mas você pode usar um lookahead para o mesmo efeito:

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

Isso realiza essencialmente uma pesquisa separada por dois separadores consecutivos e falha a correspondência se encontrar um. O corpo principal, então, só precisa garantir que todos os caracteres sejam alfanuméricos ou separadores, com o primeiro e o último sendo alfanuméricos. Como esses dois são obrigatórios, o nome deve ter pelo menos dois caracteres.

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

Este é o seu próprio regex, e requer que a string inicie e termine com dois caracteres alfanuméricos, e se houver dois separadores dentro da string, tem que haver exatamente dois alfanuméricos entre eles. Então ab , ab-cd e ab-cd-ef irão combinar, mas a , ab e abc não.

Além disso, como alguns dos comentadores apontaram, o (_|-| ) no seu regex deve ser [-_ ] . Essa parte não está incorreta , mas se você tiver uma escolha entre uma alternância e uma class de caractere, você deve sempre seguir com a class de caractere: elas são mais eficientes e mais legíveis.

Novamente, não estou preocupado se "alfanumérico" deve include caracteres não-ASCII, ou o significado exato de "espaço", apenas como aplicar uma política de separadores internos não contíguos com uma expressão regular.

Você expressão regular pode ser simplificada para:

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

Visualizado com o Regexper :

Visualização de regex de validação de nome de usuário.

Como você pode ver, um nome de usuário sempre precisa começar com um caractere alfanumérico. Caracteres especiais ( _ , , - ) tem que ser seguido por um caractere alfanumérico. O último caractere deve ser um caractere alfanumérico.

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

é um 0 ou mais repetições de alphanum, dashspace, alphanum.

Então, isso corresponderia

 a_aa_aa_a 

mas não

 aaaaa 

O regexp completo não pode corresponder

 a_aaaaaaaaa_a for example. 

Vamos olhar para o que você quer:

 * 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 underscolors, two hypens or two spaces in a row * Cannot have a underscore, hypen or space at the start or end 

O começo é simples … apenas combine um alfanum, então (gravando os dois na regra de linha) um (alfanum ou espaço de traço) * e no e um alfanum de novo.

Para evitar os dois traços consecutivos, você provavelmente precisará entender lookahead / lookbehind.

Ah, e sobre a outra resposta: Por favor, baixe o Espresso, REALMENTE ajuda você a entender essas coisas.

Eu sugiro escrever alguns testes de unidade para colocar o Regex em seus ritmos. Isso também ajudará alguns meses a partir de agora, quando você encontrar um problema com o Regex e precisar atualizá-lo.

  1. Alfanumérico não é apenas [a-zA-Z0-9] , é acentuado, cirílico, grego e outras letras, que podem ser usadas no nome de usuário.

  2. (_|-| ) pode ser substituído pela class de caractere [-_ ]

Usando a class de caracteres POSIX para caracteres alfanuméricos para fazer com que funcione para caracteres acentuados e outros caracteres alfabéticos estrangeiros:

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

Mais eficiente (evita capturas):

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

Eles também evitam sequências de mais de um espaço / hífen / sublinhado em combinação. Não se segue da sua especificação se isso é desejável, mas o seu próprio regex parece indicar que é isso que você quer.

Outra recomendação para o Expresso 3.0 aqui – muito fácil de usar e construir cordas com.

Seu regex não funciona. A parte difícil é a verificação de espaços / hífens consecutivos. Você poderia usar este, que usa look-behind:

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

Pelo que parece, essa regra não combina com algo como “a_bc”, “ab_c”, “a_b” ou “a_b_c”.

Tente: /^[a-zA-Z0-9]+([_\s\-]?[a-zA-Z0-9])*$/ que coincide com os casos acima, mas não qualquer combinação de espaços, traços ou ressalta ao lado do outro. Por exemplo: “_-” ou “_” não são permitidos.