Buscar y reemplazar

Búsqueda y/o reemplazo de fragmentos de textos


Una operación muy frecuente y habitual en Javascript, es la de comprobar la existencia de un texto, buscar o incluso reemplazar por otro texto. Dependiendo del caso, hará falta uno u otro, por lo que lo primero que debes tener claro es saber cuál necesitas. Piensa que, aunque la sintaxis o el uso de uno de ellos te resulte más sencillo que otro, hay tareas que puede que no necesites realizar gratuitamente:

  • 🔍 Comprobación (🔍): La más ligera de las tres. Sólo comprueba si existe el fragmento de texto.
  • 🕵️‍♀️ Búsqueda (🔍+🕵️‍♀️): Busca un fragmento de texto y devuelve encontrado (posición, texto...).
  • 🔁 Reemplazo (🔍+🕵️‍♀️+🔁): Realiza una búsqueda de un texto y además un reemplazo. Suele ser más costoso.

Comprobación en textos

Los siguientes métodos se utilizan para realizar algún tipo de comprobación y saber si un fragmento de texto está incluído en un :

Método Descripción
.startsWith(text, from) Comprueba si el texto comienza por text.
.endsWith(text, to) Comprueba si el texto termina por text.
.includes(text, from) Comprueba si el texto contiene el subtexto text.

Observa que en cada método tienes un segundo parámetro opcional, donde se puede indicar desde donde quieres empezar a comprobar (en el caso de from), o hasta donde quieres comprobar (en el caso de to).

  • El método .startsWith() devolverá true si el comienza por text. De lo contrario, false.
  • El método .endsWith() devolverá true si el acaba en text. De lo contrario, false.
  • El método .includes() devolverá true si el contiene text. De lo contrario, false.

Veamos algunos ejemplos:

const text = "Manz";

text.startsWith("M");     // true  ('Manz' empieza por 'M')
text.startsWith("a", 1);  // true  ('anz' empieza por 'a')
text.endsWith("o");       // false ('Manz' no acaba en 'o')
text.endsWith("n", 3);    // true  ('Man' acaba en 'n')
text.includes("an");      // true  ('Manz' incluye 'an')
text.includes("M", 1);    // false ('anz' no incluye 'M')

Ten en cuenta que los del segundo parámetro, lo que hacen es acortar el (por el inicio o por el final) antes de realizar la comprobación.

Búsqueda de cadenas de textos

Si necesitamos realizar una búsqueda de un texto (que muchas veces no tenemos claro como es) y queremos obtener información como la posición o las búsquedas encontradas, y los métodos del tema anterior de posiciones y substrings no nos sirven (o se nos quedan cortos), podemos utilizar alguno de los siguientes:

Método Descripción
.search(regexp) Busca un patrón que encaje con regexp y devuelve la posición encontrada.
.match(regexp) Idem a la anterior, pero devuelve las coincidencias encontradas.
.matchAll(regexp) Idem a la anterior, pero devuelve un iterador para iterar por cada coincidencia.

Estas búsquedas toman por parámetro expresiones regulares, por lo que suelen ser más potentes y flexibles que buscar sólo por texto. La diferencia fundamental entre ellas es la siguiente:

  • El método .search() devuelve la posición de la primera ocurrencia. -1 si no se encuentra.
  • El método .match() devuelve un con las coincidencias encontradas. null si no se encuentran.
  • El método .matchAll() devuelve un iterador para poder recorrer las coincidencias encontradas.

Veamos algunos ejemplos:

const text = "El gato, el perro y el pato.";
const regexp = /.a.o/g;

text.search(regexp);   // 3, porque la primera coincidencia ocurre en la posición 3 (gato)
text.match(regexp);    // ["gato", "pato"], las dos coincidencias encontradas

Por otro lado, el método .matchAll() es un poco más avanzado, y permite realizar la misma acción que .match() pero devolviendo un iterador, lo que nos permite recorrerlo en un bucle:

const text = "El gato, el perro y el pato.";
const regexp = /.a.o/g;

const iterator = text.matchAll(regexp);
for (let ocurrence of iterator) {
  console.log(ocurrence);
}

// ['gato', index: 3, input: 'El gato, el perro y el pato.', groups: undefined]
// ['pato', index: 23, input: 'El gato, el perro y el pato.', groups: undefined]

También es posible utilizar .matchAll() desestructurando su resultado, lo que nos permitirá acceder a la información de una forma más directa:

const text = "El gato, el perro y el pato.";
const regexp = /.a.o/g;
const results = [...text.matchAll(regexp)];    // ["gato", "pato"]

results.length     // 2
results[0].index   // 3
results[1].index   // 23

Para comprender bien el funcionamiento de este método, quizás sería mejor echar un vistazo al tema de Arrays y de Expresiones regulares, que se aborda unos capítulos más adelante.

Reemplazar cadenas de texto

Si lo que necesitamos es reemplazar un texto, tenemos a nuestra disposición una serie de métodos, tanto en versión donde buscas mediante un , como en versión donde buscas mediante una :

Método Descripción
.replace(text, newText) Reemplaza la primera aparición del text por newText.
.replace(regexp, newText) Idem, pero busca a partir de una en lugar de un .
.replaceAll(text, newText) Reemplaza todas las apariciones del texto text por newText.
.replaceAll(regexp, newText) Idem, pero busca a partir de una en lugar de un .

Observa que dichos métodos se pueden resumir en lo siguiente:

  • El método replace() reemplaza solo la primera aparición de un texto (salvo se use regexp global)
  • El método replaceAll() reemplaza todas las apariciones de un texto.

Veamos algunos ejemplos para ilustrarlo mejor.

Reemplazar textos

En este caso, usamos los métodos .replace() y .replaceAll():

const text = "Hola gato, ¿eres un perro o eres un pato?";

// Reemplazar la primera ocurrencia
text.replace("g", "p");                     // "Hola pato, ¿eres un perro o eres un pato?"
text.replace("g", "p").replace("o", "a");   // "Hala pato, ¿eres un perro o eres un pato?"

// Reemplazar todas las ocurrencias
text.replaceAll("e", "i");                  // "Hola gato, ¿iris un pirro o iris un pato?"
text.replace(/e/g, "i");                    // "Hola gato, ¿iris un pirro o iris un pato?"

Ten en cuenta que text no cambia (no muta), es decir, el método .replace() devuelve un nuevo con el texto original reemplazado. En los ejemplos anteriores, cada linea está actuando sobre la constante text de la primera línea.

El primer grupo, reemplaza sólo la primera ocurrencia encontrada. Observa que el segundo ejemplo del primer grupo, encadenamos varios .replace() consecutivos, por lo que se reemplaza la primera ocurrencia de g por p y del resultado, se reemplaza la primera ocurrencia de o por a.

El segundo grupo, por su parte, se utiliza .replaceAll() o .replace() con una expresión regular global, por lo que se reemplazan todas las ocurrencias.

Reemplazar todos los textos

Como hemos dicho, la forma más potente de reemplazar todas las ocurrencias, es utilizando .replace() con una expresión regular global. Las expresiones regulares permiten crear patrones complejos que coicindan en múltiples casos. Por ejemplo, el siguiente caso reemplaza todas las letras vocales por una letra i:

const daenerys = "Javascript es un gran lenguaje";

daenerys.replace(/[aeou]/g, "i");     // 'Jiviscript is in grin lingiiji'

Desde ECMAScript es posible utilizar replaceAll() para reemplazar todas las ocurrencias de un texto o de una expresión regular. Funciona exactamente igual que replace(), sólo que reemplaza todas las ocurrencias en vez de solamente la primera.

Función para reemplazar

Además, tanto el método .replace() como el método .replaceAll(), nos permite indicar, como segundo parámetro una en lugar de un , permitiendo utilizar dicha función para realizar un reemplazo. En lugar de simplemente reemplazar por un , se reemplaza por lo que devuelve dicha .

Observa ahora, la versión del .replace() donde le pasamos un segundo parámetro que es una que reemplaza el texto encontrado:

const text = "Hola gato, ¿eres un perro o eres un pato?";
const replaceAction = (value) => `=>${value}<=`;

text.replace(/.ato/g, replaceAction);
// "Hola =>gato<=, ¿eres un perro o eres un =>pato<=?"

text.replaceAll("un", replaceAction);
// "Hola gato, ¿eres =>un<= perro o eres =>un<= pato?"

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev