Estoy tratando de hacer coincidir cada \t en el espacio en blanco inicial de una línea para poder reemplazarlos con dos espacios. Esto es trivial con una mirada hacia atrás ilimitada (es decir, de longitud variable).
text.replace(/(?<=^\s*)\t/gm, ' ')Desafortunadamente, este código se ejecuta en iOS y, por alguna razón, Safari e iOS aún tienen que implementar lookbehinds , y mucho menos lookbehinds ilimitados.
Sé que hay soluciones alternativas para lookbehinds , pero parece que no puedo hacer que funcionen las que he visto.
Preferiría no capturar ningún carácter aparte de cada pestaña, pero si no hay otra forma, podría capturar caracteres alrededor de las pestañas en grupos de captura y agregar $1 , etc., a mi cadena de reemplazo.
const text = ` \t\ta \tb \t \tc\td \te ` const expected = ` a b c\td \te ` // throws error in iOS, which does not support lookbehinds // const regex = /(?<=^\s*)\t/gm; const regex = /to-do/gm; const result = text.replace(regex, ' ') console.log(`Text: ${text}`) console.log(`Expected: ${expected}`) console.log(`Result: ${result}`) console.log(JSON.stringify([ expected, result ], null, 2)) if (result === expected) { console.info('Success! 😃') } else { console.error('Failed 😞') }Actualizar
Una solución menos que ideal sería usar dos expresiones regulares y una función de reemplazo.
const text = ` \t\ta \tb \t \tc\td \te ` const expected = ` a b c\td \te ` const result = text.replace(/^\s*/gm, m => m.replace(/\t/g, ' ')) if (result === expected) { console.info('Success! 😃') } else { console.error('Failed 😞') }Una vez más, menos que ideal. soy un purista
Puede usar esta solución de Javascript sin involucrar looknbehind:
const text = ` \t\ta \tb \t \tc\td \te `; var repl = text.replace(/^[ \t]+/mg, g => g.replace(/\t/g, ' ')); console.log(repl);Aquí hay una solución de Ruby, en caso de que un lector desee publicar una solución de Javascript basada en ella.
rgx = /[az].*|\t/ str.gsub(rgx) { |s| s[0] == "\t" ? ' ' : s } donde str contiene la cadena que se va a modificar.
La expresión regular es una alternancia de dos partes:
[az] # match a lower-case letter .* # match zero or more characters (to end of string) | # or \t # match a tab Cada coincidencia se pasa al "bloque" ( { |s| ...} ) y se mantiene en la variable de bloque s . Si el primer carácter de la coincidencia es un tabulador, se devuelven dos espacios; sino se devuelve s . Si [az].* coincide, no habrá más coincidencias porque el resto de la cadena (posiblemente incluidas las tabulaciones) se habrá consumido.
En Python, se usaría una lambda en lugar del bloque de Ruby, algo así como
lambda m: ' ' if m.group()[0] == "\t" else m.group()