20º junio 2020

Clases de caracteres

Considera una tarea práctica: tenemos un número de teléfono como "+7(903)-123-45-67", y debemos convertirlo en número puro: 79031234567.

Para hacerlo, podemos encontrar y eliminar cualquier cosa que no sea un número. La clase de caracteres pueden ayudar con eso.

Una clase de caracteres es una notación especial que coincide con cualquier símbolo de un determinado conjunto.

Para empezar, exploremos la clase “dígito”. Está escrito como \d y corresponde a “cualquier dígito”.

Por ejemplo, busquemos el primer dígito en el número de teléfono:

let str = "+7(903)-123-45-67";

let regexp = /\d/;

alert( str.match(regexp) ); // 7

Sin la bandera (flag) g, la expresión regular solo busca la primera coincidencia, es decir, el primer dígito \d.

Agreguemos la bandera g para encontrar todos los dígitos:

let str = "+7(903)-123-45-67";

let regexp = /\d/g;

alert( str.match(regexp) ); // array de coincidencias: 7,9,0,3,1,2,3,4,5,6,7

// hagamos el número de teléfono de solo dígitos:
alert( str.match(regexp).join('') ); // 79031234567

Esa fue una clase de caracteres para los dígitos. También hay otras.

Las más usadas son:

\d (“d” es de dígito")
Un dígito: es un caracter de 0 a 9.
\s (“s” es un espacio)
Un símbolo de espacio: incluye espacios, tabulaciones \t, líneas nuevas \n y algunos otros caracteres raros, como \v, \f y \r.
\w (“w” es carácter de palabra)
Un carácter de palabra es: una letra del alfabeto latino o un dígito o un guión bajo _. Las letras no latinas (como el cirílico o el hindi) no pertenecen al \w.

Por ejemplo, \d\s\w significa un “dígito” seguido de un “carácter de espacio” seguido de un “carácter de palabra”, como 1 a.

Una expresión regular puede contener símbolos regulares y clases de caracteres.

Por ejemplo, CSS\d coincide con una cadena CSS con un dígito después:

let str = "¿Hay CSS4?";
let regexp = /CSS\d/

alert( str.match(regexp) ); // CSS4

También podemos usar varias clases de caracteres:

alert( "Me gusta HTML5!".match(/\s\w\w\w\w\d/) ); // ' HTML5'

La coincidencia (cada clase de carácter de la expresión regular tiene el carácter resultante correspondiente):

Clases inversas

Para cada clase de caracteres existe una “clase inversa”, denotada con la misma letra, pero en mayúscula.

El “inverso” significa que coincide con todos los demás caracteres, por ejemplo:

\D
Sin dígitos: cualquier carácter excepto \d, por ejemplo, una letra.
\S
Sin espacio: cualquier carácter excepto \s, por ejemplo, una letra.
\W
Sin carácter de palabra: cualquier cosa menos \w, por ejemplo, una letra no latina o un espacio.

Al comienzo del capítulo vimos cómo hacer un número de teléfono solo de números a partir de una cadena como +7(903)-123-45-67: encontrar todos los dígitos y unirlos.

let str = "+7(903)-123-45-67";

alert( str.match(/\d/g).join('') ); // 79031234567

Una forma alternativa y más corta es usar el patrón sin dígito \D para encontrarlos y eliminarlos de la cadena:

let str = "+7(903)-123-45-67";

alert( str.replace(/\D/g, "") ); // 79031234567

Un punto es “cualquier carácter”

El patrón punto (.) es una clase de caracteres especial que coincide con “cualquier carácter excepto una nueva línea”.

Por ejemplo:

alert( "Z".match(/./) ); // Z

O en medio de una expresión regular:

let regexp = /CS.4/;

alert( "CSS4".match(regexp) ); // CSS4
alert( "CS-4".match(regexp) ); // CS-4
alert( "CS 4".match(regexp) ); // CS 4 (el espacio también es un carácter)

Tenga en cuenta que un punto significa “cualquier carácter”, pero no la “ausencia de un carácter”. Debe haber un carácter para que coincida:

alert( "CS4".match(/CS.4/) ); // null, no coincide porque no hay caracteres entre S y 4

Punto es igual a la bandera “s” que literalmente retorna cualquier carácter

Por defecto, punto no coincide con el carácter de línea nueva \n.

Por ejemplo, la expresión regular A.B coincide con A, y luego B con cualquier carácter entre ellos, excepto una línea nueva \n:

alert( "A\nB".match(/A.B/) ); // null (sin coincidencia)

Hay muchas situaciones en las que nos gustaría que punto signifique literalmente “cualquier carácter”, incluida la línea nueva.

Eso es lo que hace la bandera s. Si una expresión regular la tiene, entonces . coincide literalmente con cualquier carácter:

alert( "A\nB".match(/A.B/s) ); // A\nB (coincide!)
El patrón (.) no es compatible con Firefox (< 78), IE, Edge (< 79)

Consulte https://caniuse.com/#search=dotall para conocer el soporte actualizado. Al momento de escribirse este manual, no estaban soportados.

Afortunadamente, hay una alternativa, que funciona en todas partes. Podemos usar una expresión regular como [\s\S] para que coincida con “cualquier carácter”.

alert( "A\nB".match(/A[\s\S]B/) ); // A\nB (coincide!)

El patrón [\s\S] literalmente dice: “con carácter de espacio O sin carácter de espacio”. En otras palabras, “cualquier cosa”. Podríamos usar otro par de clases complementarias, como [\d\D], eso no importa. O incluso [^], que significa que coincide con cualquier carácter excepto nada.

También podemos usar este truco si queremos ambos tipos de “puntos” en el mismo patrón: el patrón actual . comportándose de la manera regular (“sin incluir una línea nueva”), y la forma de hacer coincidir “cualquier carácter” con el patrón [\s\S] o similar.

Presta atención a los espacios

Por lo general, prestamos poca atención a los espacios. Para nosotros, las cadenas 1-5 y 1 - 5 son casi idénticas.

Pero si una expresión regular no tiene en cuenta los espacios, puede que no funcione.

Intentemos encontrar dígitos separados por un guión:

alert( "1 - 5".match(/\d-\d/) ); // null, sin coincidencia!

Vamos a arreglarlo agregando espacios en la expresión regular \d - \d:

alert( "1 - 5".match(/\d - \d/) ); // 1 - 5, funciona ahora
// o podemos usar la clase \s:
alert( "1 - 5".match(/\d\s-\s\d/) ); // 1 - 5, tambien funciona

Un espacio es un carácter. Igual de importante que cualquier otro carácter.

No podemos agregar o eliminar espacios de una expresión regular y esperar que funcione igual.

En otras palabras, en una expresión regular todos los caracteres importan, los espacios también.

Resumen

Existen las siguientes clases de caracteres:

  • \d – dígitos.
  • \D – sin dígitos.
  • \s – símbolos de espacio, tabulaciones, líneas nuevas.
  • \S – todo menos \s.
  • \w – letras latinas, dígitos, guión bajo '_'.
  • \W – todo menos \w.
  • . – cualquier caracter, si la expresión regular usa la bandera 's', de otra forma cualquiera excepto línea nueva \n.

…¡Pero eso no es todo!

La codificación Unicode, utilizada por JavaScript para las cadenas, proporciona muchas propiedades para los caracteres, como: a qué idioma pertenece la letra (si es una letra), es un signo de puntuación, etc.

Se pueden hacer búsquedas usando esas propiedades. Y se requiere la bandera u, analizada en el siguiente artículo.

Mapa del Tutorial

Comentarios

lea esto antes de comentar…
  • Si tiene sugerencias sobre qué mejorar, por favor enviar una propuesta de GitHub o una solicitud de extracción en lugar de comentar.
  • Si no puede entender algo en el artículo, por favor explique.
  • Para insertar algunas palabras de código, use la etiqueta <code>, para varias líneas – envolverlas en la etiqueta <pre>, para más de 10 líneas – utilice una entorno controlado (sandbox) (plnkr, jsbin, codepen…)