3

I have a string containing colour escape sequences, like that:

"white text \x1b[33m yellow text \x1b[32m green text"

Now I need to replace all occurences of a certain escape sequence. I only get the escape sequence I shall look for, that's what I have. As far as I know, the only way in JavaScript to replace all occurences of something is to use regular expressions.

// replace all occurences of one sequence string with another
function replace(str, sequence, replacement) {
  // get the number of the reset colour sequence
  code = sequence.replace(/\u001b\[(\d+)m/g, '$1');
  // make it a regexp and replace all occurences with the start colour code
  return str.replace(new RegExp('\\u001b\\[' + code + 'm', 'g'), replacement);
}

So, I am getting the escape sequence I want to search for, then I use a regular expression to get a number out of that sequence just to construct another regular expression that would search for the escape sequence. Isn't there an easier, nicer way?

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • This looks cool, are you sharing your final product anywhere? – mrtsherman Dec 16 '11 at 06:54
  • It is on github via https://github.com/strathausen/culoare and on npm via 'npm install culoare' – Johann Philipp Strathausen Dec 16 '11 at 06:57
  • 1
    It's hard to see what is going on here, especially if you are not familiar with coffeescript. An example with input parameters and output would be a good addition. What is the content of `o`? Something like `\u001b[99m`, so the `code` only contains the number? If so, then you are just adding a backslash before the `[` to make it a regex. That could be done in other ways, but why even use a regex in that case? Could probably do `str.replace o, a`. – Qtax Dec 16 '11 at 12:03
  • Oh my goodness... the whole example is overly complicated and not to the point. I am just writing a new one that is just about searching for those sequences. And in JS. BTW, just using replace without the RegExp would only replace it once. – Johann Philipp Strathausen Dec 16 '11 at 14:15

2 Answers2

1

If your problem is what I think it i, I think the easier and nicer way is just escaping your pattern and passing it directly to the RegExp constructor, as seen in this old question of mine

How do I do global string replace without needing to escape everything?

function escape(s) {
    return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
};

function replace_all(str, pattern, replacement){
    return str.replace( new RegExp(escape(pattern), "g"), replacement);
}

replace_all(my_text, "\x1b[33m", "REPLACEMENT")
Community
  • 1
  • 1
hugomg
  • 68,213
  • 24
  • 160
  • 246
0

The original solution in the OP is quite efficient and has only two problems as I see it.

  1. The "code = ..." statement needs a var - As-is it is polluting the global namespace.
  2. The "code = ..." statement needs some error checking to handle bad sequence input.

Here's how I'd improve it:

// replace all occurrences of one ANSI escape sequence with another.
function replace(str, sequence, replacement) {
  // Validate input sequence and extract color number.
  var code = sequence.match(/^\x1b\[(\d+)m$/);
  if (!code) {  // Handle invalid escape sequence.
    alert('Error! Invalid escape sequence');
    return str;
  }
  // make it a regexp and replace all occurrences with the start color code
  return str.replace(new RegExp('\\x1b\\[' + code[1] + 'm', 'g'), replacement);
}
ridgerunner
  • 33,777
  • 5
  • 57
  • 69