Como verificar se uma string contém letra minúscula, letra maiúscula, caractere especial e dígito?

Andei pesquisando muito e não encontrei uma resposta para minha pergunta:

Como posso verificar com uma expressão regular se uma string contém pelo menos um de cada um destes:

  • Letra Maiúscula
  • Letra minúscula
  • Dígito
  • Caráter especial: ~`!@#$%^&*()-_=+\|[{]};:'",/?

Então eu preciso de pelo menos uma letra maiúscula e pelo menos uma letra pequena e pelo menos um dígito e pelo menos um caractere especial.

Tenho certeza de que a resposta é muito simples, mas não consigo encontrar. Qualquer ajuda é muito apreciada.

Isso faz o que você quer em java como um único regex, embora eu pessoalmente use algo como a solução fornecida por Mark Rhodes. Isso vai ficar ridículo rápido (se já não é …) como as regras ficam mais complicadas.

 String regex = "^(?=.*?\\p{Lu})(?=.*?[\\p{L}&&[^\\p{Lu}]])(?=.*?\\d)" + "(?=.*?[`~!@#$%^&*()\\-_=+\\\\\\|\\[{\\]};:'\",<.>/?]).*$" 
  1. ^ Isso corresponde ao começo da string. Não é estritamente necessário que isso funcione, mas acho que ajuda a capacidade de leitura e compreensão. Além disso, usá-lo quando você costuma fazer uma grande melhoria de desempenho e quase nunca é uma penalidade.

  2. (? = X ) Isso é chamado de lookahead positivo. Basicamente, o que estamos dizendo é: “O início da string (^) deve ser seguido por essa coisa X para uma correspondência, mas NÃO avance o cursor até o final de X , permaneça no início da linha. ( essa é a parte “look ahead”.)

  3. *? \ p {Lu} come caracteres após o início da linha até encontrar uma letra maiúscula. Isso não coincidirá se nenhuma letra maiúscula for encontrada. Usamos \ p {Lu} em vez de AZ porque não queremos que pessoas de outras partes do mundo levantem as mãos e queixem-se de como nosso software foi escrito por um americano ignorante.

  4. Agora voltamos para o início da linha (voltamos porque usamos lookahead) e começamos uma busca por. *? [\ P {L} && [^ \ p {Lu}]] abreviação de “todas as letras, menos as capitais “(portanto, corresponde a letras minúsculas).

  5. * * \ d +. *? [`~! @ # $% ^ & * () \ -_ = + \\\ | \ [{\]};: ‘\”, <.> /?] repetir para dígitos e para sua lista de caracteres especiais.

  6. * $ Combine todo o resto até o final da linha. Fazemos isso apenas por causa da semântica dos methods ‘matches’ em java que verificam se a string inteira é uma correspondência para o regex. Você pode deixar essa parte e usar o método Matcher # find () e obter o mesmo resultado.

  7. A coruja é um dos melhores livros já escritos sobre qualquer assunto técnico. E é curto e rápido de ler. Eu não posso recomendar o suficiente.

Expressões regulares não são muito boas para testes em que você exige que todas as várias condições sejam atendidas.

A resposta mais simples, portanto, não é tentar testá-los todos ao mesmo tempo, mas apenas tentar cada uma das quatro classs por vez.

Seu código pode ser um pouco mais lento, mas será mais fácil de ler e manter, por exemplo

 public boolean isLegalPassword(String pass) { if (!pass.matches(".*[AZ].*")) return false; if (!pass.matches(".*[az].*")) return false; if (!pass.matches(".*\\d.*")) return false; if (!pass.matches(".*[~!.......].*")) return false; return true; } 

EDITAR as aspas fixas – vem fazendo muita programação danada com JS …

Eu concordo que a resposta do @Alnitak é a mais fácil de ler, no entanto, sofre do fato de que tem que avaliar os regexs cada vez que é executado. Como os regex são fixos, faz sentido compilá-los e compará-los. por exemplo, algo como:

  private static final Pattern [] passwordRegexes = new Pattern[4]; { passwordRegexes[0] = Pattern.compile(".*[AZ].*"); passwordRegexes[1] = Pattern.compile(".*[az].*"); passwordRegexes[2] = Pattern.compile(".*\\d.*"); passwordRegexes[3] = Pattern.compile(".*[~!].*"); } public boolean isLegalPassword(String pass) { for(int i = 0; i < passwordRegexes.length; i++){ if(!passwordRegexes[i].matcher(pass).matches()) return false; } return true; } 

Quando executado 100.000 vezes em uma senha de 10 caracteres, o código acima foi duas vezes mais rápido. Embora, eu acho que agora você poderia dizer que esse código é mais difícil de ler! Deixa pra lá!

Como elas não aparecerão em nenhuma ordem específica, você precisará de declarações antecipadas para cada class de caracteres necessária:

 (?=.*[AZ])(?=.*[az])(?=.*[0-9])(?=.*[~!@#$%\^&*()\-_=+\|\[{\]};:'",<.>/?]) 

(OBSERVAÇÃO: como barra invertida, circunflexo, hífen e colchetes podem ser especiais dentro de um intervalo, eles devem ter escape de barra invertida se aparecerem no intervalo, conforme mostrado na quarta asserção de antecipação.)

Esta construção pode ser consideravelmente mais legível usando espaços em branco e comentários, se sua variante regex suportar o modificador x . Em java.util.regex , você pode fazer:

 (?x) # extended syntax (?=.*[AZ]) # look ahead for at least one upper case (?=.*[az]) # look ahead for at least one lower case (?=.*[0-9]) # look ahead for at least one numeral (?=.*[~!@#$%\^&*()\-_=+\|\[{\]};:'",<.>/?]) # look ahead for at least one of the listed symbols 

Você está procurando por classs de personagens .

  • Letra grande: [AZ]
  • Letra pequena: [az]
  • Dígito: [0-9] ou \ d
  • Caráter especial: [^ A-Za-z0-9] (Ou seja, nenhum dos outros, onde … nega a class)

Se você quiser testar ‘this’ ou ‘that’, você pode combinar esses intervalos. Por exemplo, letras grandes ou pequenas seriam [A-Za-z] .

\w : é usado para correspondência alfanumérica (os alfabetos podem ser grandes ou pequenos)
\W : é usado para correspondência de caracteres especiais

Eu acho que este RegEx será útil para você:

 [\w|\W]+ 

Aqui está um bom Simulador RegEx , você pode usá-lo para construir seu próprio RegEx.