Nik Hendricks
Nik Hendricks

Reputation: 294

regex replace last occurance of number in between 2 chars javascript

I am trying to replace the last number of each match in between parenthesis.

so if I had cos(3 * 3)

before this regex

result = result.replace(/\d+(?:\.\d+)?/g, x => `${x}deg`)

would turn cos(3 * 3) into cos(3deg * 3deg)

I need only the last number to be changed to deg

So if I had cos(3 * 3) + cos(3 * 2) it would be cos(3 * 3deg) + cos(3 * 2deg)

What regular expression magic could I use to do this.

Upvotes: 1

Views: 135

Answers (3)

Peter Seliger
Peter Seliger

Reputation: 13417

... /\((?<first>.*?)(?<last>[\d.]+)\)/g ...

// see ... [https://regex101.com/r/aDXe3B/1]
const regXLastNumberWithinParentheses =
  /\((?<first>.*?)(?<last>[\d.]+)\)/g;

const sampleData =
`cos(3 * 3) + cos(3 * 24.5), cos(2 * 3) + cos(3 * 2.4)
cos(3 * 3.4) + cos(3 * 45), cos(4 * 2) + cos(3 * 245)`;

console.log(
  sampleData.replace(
    regXLastNumberWithinParentheses,
    (match, first, last) => `(${ first }${ last }deg)`
  )
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

1st Edit

Any idea why in this (3*(2+1+1)-12/5) is coming out as (3*(2+1+1deg)-12/5) it needs to match the last number regardless so it would be (3 *(2+1+1deg) - 23/5deg) – Nik Hendricks

@NikHendricks ... "Any idea why ...?" Yes of cause. Though the above regex matches anything and a final number in between parentheses, it does so just for un-nested parentheses (any nested structures can not be recognized). ... Question: Could one assume that the passed string does always feature validly nested parentheses? If yes, it leads to more straightforward regex replacement patterns because a regex then does not need to also validate the parentheses syntax. – Peter Seliger

... regex update ... /(?<![.\d])(?<number>\d*(?:\.\d+)?)\s*\)/g

// see ... [https://regex101.com/r/aDXe3B/2]
const regXLastNumberBeforeClosingParenthesis =
  /(?<![.\d])(?<number>\d*(?:\.\d+)?)\s*\)/g;

const sampleData =
`cos(3 * 3) + cos(3 * 24.5  ), cos(2 * 3  ) + cos(3 * 2.4)
cos(3 * 3.4) + cos(3 * 45  ), cos(4 * 2  ) + cos(3 * 245)

(3 * (2 + 1 + 1) - 23/5)`;

console.log(
  sampleData.replace(
    regXLastNumberBeforeClosingParenthesis,
    (match, number) => `${ number }deg)`
  )
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

2nd Edit

for me the desired result for 3*(1571-sin(1 * 12)) would be 3*(1571deg -sin(1 * 12deg)) the last or only occurrence of a number is replaced with xdeg – Nik Hendricks

... regex update ... /(?<number>(?<!\.)\d+(?:\.\d+)?|(?<![\d.])(?:\.\d+)(?!\.))(?<termination>\s*[-+)])/g

// see ... [https://regex101.com/r/aDXe3B/3]
const regXValidNumberBeforePlusOrMinusOrClosingParenthesis =
  /(?<number>(?<!\.)\d+(?:\.\d+)?|(?<![\d.])(?:\.\d+)(?!\.))(?<termination>\s*[-+)])/g;

const sampleData =
`cos(3 * 3) + cos(3 * 24.5  ), cos(2 * 3  ) + cos(3 * .2.4)
cos(3 * 3.4) + cos(3 * 45  ), cos(4 * .24) + cos(3 * 245 )

(3 *(2 + 1 + 1) - 23/5 )

3 * (1571 - sin(12))`;

console.log(
  sampleData.replace(
    regXValidNumberBeforePlusOrMinusOrClosingParenthesis, '$1deg$2'
  )
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

Regarding the last iteration/edit ... in case number validation is not important (because the input is trusted), one of cause could achieve the same result with a less strict, thus simpler, regex which does not exclusively match valid numbers ... /(?<dotsAndDigits>[.\d]+)(?<termination>\s*[-+)])/g.

Upvotes: 1

sln
sln

Reputation: 2840

The insertion position for deg is just a place between two defined Assertions.

(?<=\([^()]*\d)(?=[^()\d]*\))

https://regex101.com/r/sjw3CX/1

 (?<= \( [^()]* \d )           # Lookbehind open parenth up to last number
 (?= [^()\d]* \) )             # Lookahead no digits and must have a closing parenth

var input = " cos(3 * 3) + cos(3 * 2)"

var output = input.replace(/(?<=\([^()]*\d)(?=[^()\d]*\))/g,'deg')

console.log(output)

Upvotes: 1

JaivBhup
JaivBhup

Reputation: 865

You can simply use the closing braces to replace like this:

var result = "cos(3 * 3) + cos(3 * 245)"

result = result.replace(/(\d+)(\))/g,'$1deg)')

console.log(result)

Or just replace the last bracket.

var result = "cos(3 * 90) + sin(3 * 2)"

result = result.replace(/\)/g,'deg)')

console.log(result)

With Decimal add a character class using [] for . and digits

var result = "cos(3 * 3.4) + cos(3 * 245.5)"

result = result.replace(/([\d\.]+)(\))/g,'$1deg)')

console.log(result)

Any equation at the last number

var result = "3*(1571-sin(12))"

result = result.replace(/(\d\s{0,}\*+\d{0,})(.*\))/g,'$1$2deg')

console.log(result)

Upvotes: 1

Related Questions