问题
I'm looking for a regex to replace all leading tab characters with a single space (one space for each leading tab character.
// 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"
See this in a js fiddle: https://jsfiddle.net/onebcvu4/2/
Answer D work for me.
input.replace(/\t/gy, " ")
But I don't really understand why. Especially because, according to MDN documentation, the global (G) flag should be ignored when used with a sticky flag.
A regular expression defined as both sticky and global ignores the global flag.
Can anyone claryfy or provide another solution that works?
回答1:
Your Answer D works (and is quite clever) because g and y aren't exclusive, but it was reasonable to think they would be. Full details are in the specification here and here, but fundamentally the g makes replace repeat as long as there is a match, and y means that A) the expression only matches at lastIndex (which defaults to 0), and B) lastIndex is not updated. So you repeatedly match a \t at lastIndex and replace it until you run out of \t at lastIndex. Very clever.
If you don't want to use that one, you can also do it with an alternation and a positive look behind:
const result = input.replace(/(?:^\t|(?<=^\t*)\t)/g, " ");
Live Example:
const input = "\t\tSome text\t\tcontaining tabs";
const result = input.replace(/(?:^\t|(?<=^\t*)\t)/g, " ");
console.log(JSON.stringify(result));
Or if you're okay with passing a callback to replace, it's simpler and doesn't need lookbehind (which is relatively new, ES2018): Match all leading \t characters and replace with a string of spaces the same length:
const result = input.replace(/^(\t+)/, match => " ".repeat(match.length));
Live Example:
const input = "\t\tSome text\t\tcontaining tabs";
const result = input.replace(/^(\t+)/, match => " ".repeat(match.length));
console.log(JSON.stringify(result));
来源:https://stackoverflow.com/questions/64982135/regex-to-replace-all-leading-tab-characters-each-one-with-a-single-space