Regex, aby zastąpić wszystkie początkowe znaki tabulacji, każdy z pojedynczą spacją [duplikat]
Szukam wyrażenia regularnego, które zastąpi wszystkie początkowe znaki tabulacji pojedynczą spacją (po jednej spacji dla każdego wiodącego znaku tabulacji.
// 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"
Zobacz to na skrzypcach js: https://jsfiddle.net/onebcvu4/2/
Odpowiedź D działa dla mnie.
input.replace(/\t/gy, " ")
Ale naprawdę nie rozumiem, dlaczego. Zwłaszcza, że zgodnie z dokumentacją MDN flagę globalną (G) należy ignorować, gdy jest używana z flagą sticky.
Wyrażenie regularne zdefiniowane jako trwałe i globalne ignoruje flagę globalną.
Czy ktoś może wyjaśnić lub zapewnić inne działające rozwiązanie?
Odpowiedzi
Twoja odpowiedź D działa (i jest całkiem sprytna), ponieważ g
i y
nie jest wyłączna, ale rozsądnie było sądzić, że tak będzie. Pełne szczegóły znajdują się w specyfikacji tutaj i tutaj , ale zasadniczo g
marki replace
powtarzają się tak długo, jak długo istnieje zgodność, co y
oznacza, że A) wyrażenie pasuje tylko w lastIndex
(domyślnie 0), a B) lastIndex
nie jest aktualizowane. Więc wielokrotnie dopasowujesz \t
at lastIndex
i zastępujesz go, aż zabraknie \t
at lastIndex
. Bardzo mądry.
Jeśli nie chcesz tego używać, możesz to również zrobić z naprzemiennym spojrzeniem i pozytywnym spojrzeniem za:
const result = input.replace(/(?:^\t|(?<=^\t*)\t)/g, " ");
Przykład na żywo:
const input = "\t\tSome text\t\tcontaining tabs";
const result = input.replace(/(?:^\t|(?<=^\t*)\t)/g, " ");
console.log(JSON.stringify(result));
Lub jeśli replace
nie przeszkadza ci przekazywanie wywołania zwrotnego do , jest to prostsze i nie wymaga wyszukiwania wstecznego (co jest stosunkowo nowe, ES2018): Dopasuj wszystkie wiodące \t
znaki i zastąp ciągiem spacji o tej samej długości:
const result = input.replace(/^(\t+)/, match => " ".repeat(match.length));
Przykład na żywo:
const input = "\t\tSome text\t\tcontaining tabs";
const result = input.replace(/^(\t+)/, match => " ".repeat(match.length));
console.log(JSON.stringify(result));