Regex para reemplazar todos los caracteres de tabulación iniciales, cada uno con un solo espacio [duplicado]
Estoy buscando una expresión regular para reemplazar todos los caracteres de tabulación iniciales con un solo espacio (un espacio para cada carácter de tabulación inicial.
// input text with two leading tab characters and two tab characters elsewhere in the text
var input=" Some text containing tabs";
// A:
console.log(input.replace(/\t/g, "LEADING_TAB_"));
// prints: "LEADING_TAB_LEADING_TAB_Some textLEADING_TAB_LEADING_TAB_containing tabs"
// B:
console.log(input.replace(/\t/, "LEADING_TAB_"));
// prints: "LEADING_TAB_ Some text containing tabs"
// C:
console.log(input.replace(/^(\t)*/, "LEADING_TAB_"));
// prints: "LEADING_TAB_Some text containing tabs"
// D:
console.log(input.replace(/\t/gy, "LEADING_TAB_"));
// prints: "LEADING_TAB_LEADING_TAB_Some text containing tabs"
// E:
console.log(input.replace(/\t/y, "LEADING_TAB_"));
// prints: "LEADING_TAB_ Some text containing tabs"
Vea esto en un violín js: https://jsfiddle.net/onebcvu4/2/
La respuesta D funciona para mí.
input.replace(/\t/gy, " ")
Pero realmente no entiendo por qué. Especialmente porque, según la documentación de MDN , la bandera global (G) debe ignorarse cuando se usa con una bandera adhesiva.
Una expresión regular definida como permanente y global ignora la marca global.
¿Alguien puede claryfy o proporcionar otra solución que funcione?
Respuestas
Su respuesta D funciona (y es bastante intuitivo) debido gy y no son excluyentes, sino que era razonable pensar que sería. Los detalles completos se encuentran en la especificación aquí y aquí , pero fundamentalmente las gmarcas se replacerepiten siempre que haya una coincidencia, y ysignifica que A) la expresión solo coincide en lastIndex(que por defecto es 0), y B) lastIndexno se actualiza. Así que coinciden en repetidas ocasiones una \ten lastIndexy volver a colocarlo cuando se le acaba el \tal lastIndex. Muy inteligente.
Si no quieres usar ese, también puedes hacerlo con una alternancia y una mirada positiva hacia atrás:
const result = input.replace(/(?:^\t|(?<=^\t*)\t)/g, " ");
Ejemplo en vivo:
const input = "\t\tSome text\t\tcontaining tabs";
const result = input.replace(/(?:^\t|(?<=^\t*)\t)/g, " ");
console.log(JSON.stringify(result));
O si está de acuerdo con pasar una devolución de llamada a replace, es más simple y no necesita mirar atrás (que es relativamente nuevo, ES2018): haga coincidir todos los \tcaracteres principales y reemplácelos con una cadena de espacios de la misma longitud:
const result = input.replace(/^(\t+)/, match => " ".repeat(match.length));
Ejemplo en vivo:
const input = "\t\tSome text\t\tcontaining tabs";
const result = input.replace(/^(\t+)/, match => " ".repeat(match.length));
console.log(JSON.stringify(result));