Regex para combinar símbolos:! $% ^ & * () _ + | ~ - = `{} []:"; '<>?,. /

93

Estou tentando criar um teste Regex em JavaScript que testará uma string para conter qualquer um destes caracteres:

!$%^&*()_+|~-=`{}[]:";'<>?,./

Mais informações se você estiver interessado :)

É para um aplicativo de alteração de senha muito legal no qual estou trabalhando. Caso você esteja interessado, aqui está o resto do código.

Eu tenho uma tabela que lista os requisitos de senha e conforme os usuários finais digitam a nova senha, ele testará uma matriz de Regexes e colocará uma marca de seleção na linha da tabela correspondente se ... verificar :) Eu só preciso adicionar este no lugar do 4º item na validationmatriz.

var validate = function(password){
    valid = true;

    var validation = [
        RegExp(/[a-z]/).test(password), RegExp(/[A-Z]/).test(password), RegExp(/\d/).test(password), 
        RegExp(/\W|_/).test(password), !RegExp(/\s/).test(password), !RegExp("12345678").test(password), 
        !RegExp($('#txtUsername').val()).test(password), !RegExp("cisco").test(password), 
        !RegExp(/([a-z]|[0-9])\1\1\1/).test(password), (password.length > 7)
    ]

    $.each(validation, function(i){
        if(this)
            $('.form table tr').eq(i+1).attr('class', 'check');
        else{
            $('.form table tr').eq(i+1).attr('class', '');
            valid = false
        }
    });

    return(valid);

}

Sim, também há validação do lado do servidor correspondente!

pixelbobby
fonte
9
É muito engraçado que a resposta à sua pergunta esteja no título, com exceção de caracteres especiais de escape e barras fechadas.
sciritai
1
Por que não usar .addClass("check")e .removeClass("check")? E ver if (someBoolean == true)em código sempre me faz estremecer. Apenas faça if (someBoolean). Ou, melhor ainda, apenas faça $(".form table tr").eq(i+1).toggleClass("check", !!this); valid = valid && !!this;.
gilly
+1 @ gill3 thx pela revisão do código - ótimo feedback. Eu definitivamente usei esses métodos abreviados no passado.
pixelbobby
@ gilly3, parece funcionar muito bem no FF, mas! IE8. amo este atalho. Estou tentando descobrir o que o IE8 está fazendo de forma diferente.
pixelbobby

Respostas:

171

A expressão regular para isso é muito simples. Basta usar uma classe de personagem. O hífen é um caractere especial nas classes de caracteres, portanto, ele precisa ser o primeiro:

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

Você também precisa escapar os outros metacaracteres de expressão regular.

Editar: o hífen é especial porque pode ser usado para representar uma variedade de caracteres. Esta mesma classe de caracteres pode ser simplificada com intervalos para isto:

/[$-/:-?{-~!"^_`\[\]]/

Existem três intervalos. '$' para '/', ':' para '?' e '{' para '~'. a última sequência de caracteres não pode ser representada de forma mais simples com um intervalo:! "^ _` [].

Use uma tabela ACSII para encontrar intervalos para classes de caracteres.

Jeff Hillman
fonte
Por que não são mencionados os quantificadores \ Q e \ E para escapar da sequência de caracteres?
SerG de
Antes de encontrar essa solução, eu estava seguindo a rota de exclusão de classe de personagem: corresponder a tudo, exceto alfa, dígitos, espaço em branco, etc.
Pete Alvin
1
É do conhecimento geral que os hífens têm que vir primeiro? Eu li dezenas de respostas de SO e folhas de referência de regex. Esta é a primeira vez que ouço falar disso. Sua resposta me salvou muito drama. Obrigado!
CF_HoneyBadger
2
@SerG \Qe \Enão funcionam no mecanismo JS RegExp :(/^\Q.\E$/.test('Q+E'); // true
Paul S.
1
@ q4w56 a barra invertida não está no conjunto de caracteres especificado na pergunta original, portanto, não corresponder a barra invertida está correto. :)
Jeff Hillman
5

A maneira mais simples e curta de fazer isso:

/[^\p{L}\d\s@#]/u

Explicação

[^...] Corresponde a um único caractere não presente na lista abaixo

  • \p{L} => corresponde a qualquer tipo de letra de qualquer idioma

  • \d => corresponde a um dígito de zero a nove

  • \s => corresponde a qualquer tipo de personagem invisível

  • @# => @e# personagens

Não se esqueça de passar a usinalização (unicode).

AmirZpr
fonte
você não precisaria de um ^ para indicar não?
Webber
1
@Webber Não. Eles estão em maiúsculas e isso torna a declaração negativa. ^é necessário quando usamos \we \sem letras minúsculas.
AmirZpr
3
Isso não interpreta de forma que seja fora wou fora s, e uma vez que esses dois não se cruzam realmente, apenas deixa passar todos os personagens? (Portanto, não filtrando nada.)
Zael
2
@Zael Você está certo, a expressão regular indicada ( /[\W\S]/) deixa tudo passar. Seria uma representação mais precisa do que acredito que Amir estava chegando [^\w\s]. No primeiro caso, a expressão regular diz "corresponder a qualquer coisa que não seja alfanumérica OU que não seja espaço em branco", o que, como você mencionou, deixa tudo claro, já que os caracteres alfanuméricos não são espaços em branco e vice-versa. O último diz "corresponder a qualquer coisa que não seja alfanumérica E que não seja um espaço em branco". Obviamente, as exceções se aplicam quando os caracteres acentuados (como À) são correspondidos por [^\w\s].
Jesse
isso não inclui _ char
MikeSchem
4

Responda

/[\W\S_]/

Explicação

Isso cria uma classe de caractere removendo os caracteres de palavra, caracteres de espaço e adicionando de volta o caractere de sublinhado (pois o sublinhado é um caractere de "palavra"). Tudo o que resta são os caracteres especiais. As letras maiúsculas representam a negação de suas contrapartes em minúsculas.

\Wirá selecionar todos os caracteres não "palavra" equivalentes a [^a-zA-Z0-9_]
\Sirá selecionar todos os caracteres não "espaços em branco" equivalentes a [ \t\n\r\f\v]
_irá selecionar "_" porque nós o negamos ao usar o \We precisamos adicioná-lo novamente em

MikeSchem
fonte
MikeSchem, você acabou de me levar por uma máquina do tempo.
pixelbobby
sim, eu percebi. era antigo, mas senti que a resposta mais simples não foi postada.
MikeSchem
como isso é diferente da resposta abaixo que falha no sublinhado?
sf8193
sim, você está certo, vou modificar isso
MikeSchem
-1
// The string must contain at least one special character, escaping reserved RegEx characters to avoid conflict
  const hasSpecial = password => {
    const specialReg = new RegExp(
      '^(?=.*[!@#$%^&*"\\[\\]\\{\\}<>/\\(\\)=\\\\\\-_´+`~\\:;,\\.€\\|])',
    );
    return specialReg.test(password);
  };
Arni Gudjonsson
fonte
Não use o RegExpconstrutor quando você pode apenas usar um literal regex. Muito menos trabalho de escape (a maioria dos quais são desnecessários de qualquer maneira) e é mais eficiente também.
Bergi
Por que usar um lookahead complicado quando você pode simplesmente combinar o personagem diretamente?
Bergi
Você pode dar um exemplo @Bergi? Eu não entendo o que você está sugerindo.
Arni Gudjonsson
-1

Uma maneira simples de conseguir isso é o conjunto negativo [^ \ w \ s]. Essencialmente, isso captura:

  • Qualquer coisa que não seja um caractere alfanumérico (letras e números)
  • Qualquer coisa que não seja um espaço, tabulação ou quebra de linha (chamados coletivamente de espaço em branco)

Por alguma razão [\ W \ S] não funciona da mesma forma, não faz nenhuma filtragem. Um comentário de Zael sobre uma das respostas fornece uma espécie de explicação.

Harfel Jaquez
fonte
Não, o sublinhado está faltando e todos os caracteres fora do intervalo ASCII e a maioria dos caracteres de controle no intervalo ASCII corresponderiam a esta classe. /[^\w\s]/.test('é') # true, /[^\w\s]/.test('_') # false.
Casimir et Hippolyte
-7

Substitua todos os últimos de qualquer idioma em 'A', e se desejar, por exemplo, todos os dígitos para 0:

return str.replace(/[^\s!-@[-`{-~]/g, "A").replace(/\d/g, "0");
Yaron Landau
fonte
22
Que pergunta você está respondendo?
Toto