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

93

Estoy tratando de crear una prueba Regex en JavaScript que probará una cadena para contener cualquiera de estos caracteres:

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

Más información si está interesado :)

Es para una aplicación de cambio de contraseña genial en la que estoy trabajando. En caso de que esté interesado, aquí está el resto del código.

Tengo una tabla que enumera los requisitos de contraseña y, a medida que los usuarios finales escriben la nueva contraseña, probará una matriz de expresiones regulares y colocará una marca de verificación en la fila de la tabla correspondiente si ... verifica :) Solo necesito agregar esta en lugar del cuarto elemento de la 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);

}

Sí, también existe la correspondiente validación del lado del servidor.

pixelbobby
fuente
9
Es bastante gracioso que la respuesta a su pregunta esté en el título, con la excepción de escapar de los caracteres especiales y delimitar barras diagonales.
sciritai
1
¿Por qué no usar .addClass("check")y .removeClass("check")? Y ver if (someBoolean == true)en código siempre me da vergüenza. Solo hazlo if (someBoolean). O, mejor aún, hazlo $(".form table tr").eq(i+1).toggleClass("check", !!this); valid = valid && !!this;.
gilly3
+1 @ gill3 gracias por la revisión del código, una gran respuesta de hecho. Definitivamente he usado esos métodos abreviados en el pasado.
pixelbobby
@ gilly3, parece funcionar muy bien en FF pero! IE8. amo esta taquigrafía. Estoy tratando de averiguar qué hace IE8 de manera diferente.
pixelbobby

Respuestas:

171

La expresión regular para esto es realmente simple. Solo usa una clase de personaje. El guión es un carácter especial en las clases de caracteres, por lo que debe ser el primero:

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

También necesita escapar de los otros metacaracteres de expresión regular.

Editar: el guión es especial porque se puede usar para representar un rango de caracteres. Esta misma clase de caracteres se puede simplificar con rangos a esto:

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

Hay tres rangos. '$' a '/', ':' a '?' y '{' a '~'. la última cadena de caracteres no se puede representar más simplemente con un rango:! "^ _` [].

Use una tabla ACSII para encontrar rangos para clases de caracteres.

Jeff Hillman
fuente
¿Por qué no se mencionan los cuantificadores \ Q y \ E para escapar de la secuencia de caracteres?
SerG
Antes de encontrar esta solución, estaba siguiendo la ruta de exclusión de clases de caracteres: coincidir con todo PERO alfa, dígitos, espacios en blanco, etc.
Pete Alvin
1
¿Es de conocimiento común que los guiones deben ir primero? He leído docenas de respuestas SO y hojas de trucos de expresiones regulares, esta es la primera vez que escucho de ella. Tu respuesta me salvó mucho drama. ¡Gracias!
CF_HoneyBadger
2
@SerG \Qy \Eno funciona en el motor JS RegExp :(/^\Q.\E$/.test('Q+E'); // true
Paul S.
1
@ q4w56 barra invertida no está en el conjunto de caracteres especificado en la pregunta original, por lo que no coincidir con barra invertida es correcto. :)
Jeff Hillman
5

La forma más simple y corta de lograr esto:

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

Explicación

[^...] Coincide con un solo carácter que no está presente en la lista siguiente

  • \p{L} => coincide con cualquier tipo de letra de cualquier idioma

  • \d => coincide con un dígito del cero al nueve

  • \s => coincide con cualquier tipo de carácter invisible

  • @# => @y #personajes

No olvide pasar la ubandera (unicode).

AmirZpr
fuente
¿No necesitarías un ^ para indicar que no?
Webber
1
@Webber No. Están en capital y esto hace que la declaración sea negativa. ^es necesario cuando lo usamos \wy \sen minúsculas.
AmirZpr
3
¿No lo interpreta esto de manera que, ya sea afuera wo afuera s, y dado que esos dos realmente no se cruzan, solo deja pasar a todos los personajes? (Por lo tanto, no se filtra nada)
Zael
2
@Zael Tienes razón, la expresión regular como se indica ( /[\W\S]/) deja que todo pase. Una representación más precisa de lo que creo que quería decir Amir sería [^\w\s]. En el primero, la expresión regular dice "coincidir con cualquier cosa que no sea alfanumérica O que no sea un espacio en blanco", lo que, como mencionaste, lo deja todo, ya que los caracteres alfanuméricos no son espacios en blanco y viceversa. El último dice "coincidir con cualquier cosa que no sea alfanumérica Y que no sea un espacio en blanco". Por supuesto, se aplican excepciones en el sentido de que los caracteres acentuados (como À) coinciden con [^\w\s].
Jesse
esto no incluye el _ char
MikeSchem
4

Responder

/[\W\S_]/

Explicación

Esto crea una clase de carácter que elimina los caracteres de palabra, los espacios y vuelve a agregar el carácter de subrayado (como subrayado es un carácter de "palabra"). Todo lo que queda son los caracteres especiales. Las letras mayúsculas representan la negación de sus contrapartes minúsculas.

\Wseleccionará todos los caracteres que no sean de "palabra" equivalentes a [^a-zA-Z0-9_]
\Sseleccionará todos los caracteres que no sean "espacios en blanco" equivalentes a [ \t\n\r\f\v]
_seleccionará "_" porque lo negamos cuando usamos el \Wy necesitamos volver a agregarlo

MikeSchem
fuente
MikeSchem, me acaba de llevar a través de una máquina del tiempo.
pixelbobby
sí, lo noté. era antiguo, pero sentí que la respuesta más simple no estaba publicada.
MikeSchem
¿En qué se diferencia de la respuesta a continuación que falla en el subrayado?
sf8193
sí, tienes razón, modificaré esto
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
fuente
No use el RegExpconstructor cuando solo pueda usar un literal de expresión regular. Mucho menos trabajo de escape (la mayoría de los cuales son innecesarios de todos modos) y también es más eficiente.
Bergi
¿Por qué usar una mirada anticipada complicada cuando puedes simplemente hacer coincidir el personaje directamente?
Bergi
¿Puedes dar un ejemplo @Bergi? No entiendo lo que está sugiriendo.
Arni Gudjonsson
-1

Una forma sencilla de lograr esto es el conjunto negativo [^ \ w \ s]. Esto esencialmente atrapa:

  • Todo lo que no sea un carácter alfanumérico (letras y números)
  • Cualquier cosa que no sea un espacio, tabulación o salto de línea (denominados colectivamente espacios en blanco)

Por alguna razón, [\ W \ S] no funciona de la misma manera, no hace ningún filtrado. Un comentario de Zael sobre una de las respuestas proporciona una especie de explicación.

Harfel Jaquez
fuente
No, falta el guión bajo y todos los caracteres fuera del rango ascii y la mayoría de los caracteres de control en el rango ascii coincidirían con esta clase. /[^\w\s]/.test('é') # true, /[^\w\s]/.test('_') # false.
Casimir et Hippolyte
-7

Reemplace todos los últimos de cualquier idioma en 'A', y si lo desea, por ejemplo, todos los dígitos a 0:

return str.replace(/[^\s!-@[-`{-~]/g, "A").replace(/\d/g, "0");
Yaron Landau
fuente
22
¿Qué pregunta estás respondiendo?
Toto