I am trying to write a JavaScript replaceAll()
with a RegEx that will replace every value of x
with period*x
, as long as it is within Math.sin()
or Math.cos()
or Math.tan()
I tried this:
let fx = 'Math.tan(Math.sin(Math.cos(x)*x)*x)';
const periodRegEx = /(Math.(sin|cos|tan)(.*?)(x)([^)].*?)())/gi;
// capture group with 'Math.sin(' or 'Math.cos(' or 'Math.tan('
// capture group with 'x'
// capture group with any character except for ')'
// capture group with ')'
let newFx = fx.replaceAll(periodRegEx,('period*'+2));
But that is getting me an `illegal escape sequence error. This:
let newFx = fx.replaceAll(periodRegEx,('period*'+'2'));
Is giving me nothing, and this:
let newFx = fx.replaceAll(periodRegEx,('period*'+$2));
Is giving me a $2 not defined
error.
What I am looking for is this as the output of the replaceAll()
:
'Math.tan(Math.sin(Math.cos(period*x)*period*x)*period*x)'
3
Answers
If your code is JS (seems) you can parse and replace it with acorn and generate back JS code with astring:
It is most likely unfeasible to achieve what you need with RegEx-only oneliner, having in mind that:
A simple solution in plain JS without additional libraries would be to extract parts of expression that start with a trig function call, perform replacement only on them and concatenate back with the remainder of the formula.
Note that due to (3) also using
/((.*?x[^)]*?))/
to extract function argument will not always be sufficient.One example of such solution would be:
Doing this with a single regex expression is going to be difficult, but you can accomplish it with a recursive replace function that will handle the matches one at a time, applying placeholders, then loop back through the array of matches in reverse.