0

I have a string and would like to replace all instances of the two characters "<" and ">" together with all its surrounding whitespace (no tabs, no newlines, possibly empty) by " < " and " > ", respectively.

Can I do this with a one-liner replace regex expression?

The slow and hard way would be

while (entry.value.indexOf(" <") > -1) {
    entry.value = entry.value.replace(" <","<");
}
while (entry.value.indexOf("< ") > -1) {
    entry.value = entry.value.replace("< ","<");
}
while (entry.value.indexOf(" >") > -1) {
    entry.value = entry.value.replace(" >",">");
}
while (entry.value.indexOf("> ") > -1) {
    entry.value = entry.value.replace("> ",">");
}
entry.value = entry.value.replace("<"," < ").replace(">"," > ");

Shortening the whitespace is explained at Regex to replace multiple spaces with a single space, but I do not assume whitespaces around the two characters.

The use case I have are saving math expressions in a database to be presented on a website using MathJax. Doing so, one runs into exactly this problem, see http://docs.mathjax.org/en/latest/tex.html#tex-and-latex-in-html-documents.

Typical expressions are

"Let $i$ such that $i<j$..."
"Let $<I>$ be an ideal in..."

(the later wouldn't even render here in the preview in normal text mode.)

Christian
  • 527
  • 6
  • 19

1 Answers1

1

Copy pasting Wiktor's comment here. \s matches any whitespace character, * indicates to match 0 or more of those whitespace characters, [<>] matches any < or >, the g flag indicates to do a global replace instead of just replacing the first match, and the parentheses are to create a capture group so that we can use $1 to refer to the match as a backreference in the replacement string.

See some example input output below.

'<>' // => ' <  > ' (two spaces between the carets)
'<\t\t\n\ \n<' // => ' <  < ' (again two spaces)
'>a     \t b<    ' // => ' > a     \t b < '
'a>\n   b   <c    ' // => 'a > b < c    '

a = 'fpo<  \n>\naf      ja\tb<>\t<><>asd\npfi b.<< >    >';
b = a.replace(/\s*([<>])\s*/g, ' $1 ');

console.log(b);
Zevgon
  • 556
  • 4
  • 13
  • You could add a `.replace(/ */g, ' ');` to fix the double spaces. – Cerbrus Nov 20 '17 at 09:37
  • Because I first came up with my own answer, and before posting it, I read your comment and saw that it was almost identical. Originally, my answer was this: `a.replace(/\s*([<>])\s*/g, (match, $1) => \` ${$1} \`);` Yours is obviously cleaner syntax, so it should be the answer. I do understand the drawbacks because I also came up with the same solution. – Zevgon Nov 20 '17 at 09:55
  • You do not have to use a callback if you just need to use backreferences, string replacement patterns will do. Still, code only answers are not quite helpful for both OP and future readers, please consider adding some explanation to this solution. – Wiktor Stribiżew Nov 20 '17 at 09:58
  • @WiktorStribiżew Right, I've never been great with backreferences, but now understand them better. Good point about code only answers. I've just updated it with more info. – Zevgon Nov 20 '17 at 10:30