Reputation: 242
It will cost you $112.52 for 302 pokemon cards to complete this order
It will cost you $112.52 to complete this order
Above are two strings that I want to find the dollar value using regex. Below is my current regex:
const match = str.match(/will cost you \$(.*) for ([0-9]+) pokemon cards to complete this order|will cost you \$(.*) to complete this order/);
I can get $112.52
in match[1] and match[3] for both strings.
However with this way (([0-9]+)
), I am also matching the number of pokemon cards 302
which is NOT what I want (in match[2]). Is there a way I can ignore any number of pokemon cards and match just the dollar sign value in both strings in a single regex?
Upvotes: 0
Views: 108
Reputation: 54016
use lookbehind assertion in regex
(?<=Y)X Positive lookbehind X if after Y
(?<=\$)\d+
example: https://regex101.com/r/H7Iyb6/1
reference: https://javascript.info/regexp-lookahead-lookbehind
other way is that you can use unicode property \p
class with \u
flag
const regex = \p{Sc}\p{Nd}+.\p{Nd}+
Upvotes: 0
Reputation: 13376
A precisely matching regex had to check the validity of a number value as well which follows the leading $
. One would achieve this by regex-lookarounds where a negative lookahead would assure a single valid integer or float number value whereas the positive lookbehind would support the direct match
of the number value.
Such a regex would be as follows ...
/(?<=\$)(?:\d*\.)?\d+(?![.\d])/g
... and the description is provided by its test/playground page.
Its usage would be as follows ...
const sampleText = `
It will cost you $112.52 for 302 pokemon cards to complete this order
It will cost you $.52 for 302 pokemon cards to complete this order
It will cost you $2.52.523.45 for 302 pokemon cards to complete this order
It will cost you $.52.523.455 for 302 pokemon cards to complete this order
It will cost you $ .52 to complete this order
It will cost you $.52 to complete this order
It will cost you $112 to complete this order`;
// see ... [https://regex101.com/r/hjIoWb/1]
const regXNumberValue = /(?<=\$)(?:\d*\.)?\d+(?![.\d])/g;
console.log(
sampleText
.match(regXNumberValue)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Since lookbehinds are not supported by e.g. even the latest safari versions one has to work around it. A possible solutions was the usage of an e.g. named capturing group.
The above first provided regex then changes to ...
/\$(?<value>(?:\d*\.)?\d+)(?![.\d])/g
... where the pattern gets explained by its test/playground page.
Its usage needs to be changed too, from match
to matchAll
followed by an additional map
ping task ...
const sampleText = `
It will cost you $112.52 for 302 pokemon cards to complete this order
It will cost you $.52 for 302 pokemon cards to complete this order
It will cost you $2.52.523.45 for 302 pokemon cards to complete this order
It will cost you $.52.523.455 for 302 pokemon cards to complete this order
It will cost you $ .52 to complete this order
It will cost you $.52 to complete this order
It will cost you $112 to complete this order`;
// see ... [https://regex101.com/r/hjIoWb/2]
const regXNumberValue = /\$(?<value>(?:\d*\.)?\d+)(?![.\d])/g;
console.log(
[...sampleText.matchAll(regXNumberValue)]
.map(({ groups: { value } }) => value)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Upvotes: 0
Reputation: 156
If you just want the dollar amount and don't care about anything else in the string, you don't need to mention anything else in the string in your regex.
You could just match $ followed by numbers and dots, i.e
str.match(/\$([\d\.]+)/)
A fuller test example...
(function() {
let strs = [
"It will cost you $112.52 for 302 pokemon cards to complete this order",
"It will cost you $112.52 to complete this order"
];
strs.forEach(
(str) => {
let match = str.match(/\$([\d\.]+)/);
console.debug(match);
}
);
})();
...outputs...
Array [ "$112.52", "112.52" ]
Array [ "$112.52", "112.52" ]
Upvotes: 2