Reputation: 69
I am new to regular expression, In my project i am allowing user to put amount in shorthand as well as full digit, i have used material UI TextField for input.
Examples are:
400k - shorthand,
400.2k - shorthand,
4m - shorthand,
500. - should work
500000 - full amount
some pattern user should not be allowed to enter example are:
4.2.k,
.3k,
4...k
300.k
I have written regex which is below but it does allows to enter dot after number.
textValue.match(/^[0-9]*(\.[0-9]{0,2})*([0-9km]{1})$/) && textValue.match(/^[\d]+/)
above code first regex validates the pattern and second regex forces user to put Number because amount cannot start with string, i have wrote two separate regex as i don't understand how to put them in one regex and those regex doesn't accepts dot after number. Please can anyone give a perfect Regex to validate the above pattern in one single regular expression??
Thanks in advance
Upvotes: 2
Views: 1378
Reputation:
You can try:
^\d+\.?(?:\d+)?[KkMm]?(?<!\.[KkMm])$
Explanation of the above regex:
^, $
- Matches start and end of the line respectively.
\d+
- Matches digits 1 or more times.
\.?
- Represents 0 or 1 occurrence of.
.
[KkMm]?
- Matches optional characters from the mentioned character class.
(?<!\.[KkMm])
- Represents a negative look-behind not matching a a character after.
.
You can find the demo of the above regex in here.
const regex = /^\d+\.?(?:\d+)?[KkMm]?(?<!\.[KkMm])$/gm;
const str = `400K
4.2.K
4.3K
3.2M
300000
4....K
4K
500.
300.K`;
let m;
while ((m = regex.exec(str)) !== null) {
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`${match}`);
});
}
2nd efficient solution using alternation:
You can probably try this regex for more efficient implementation
^\d+(?:\.$|\.\d+)?[KkMm]?$
Explanation of the above regex:
^, $
- Matches start and end of the line respectively.
\d+
- Matches digits 1 or more times.
(?:\.$|\.\d+)?
- Represents a non-capturing group; matching either numbers followed by only.
or decimal numbers.
[KkMm]?
- Matches one of the mentioned characters zero or 1 time.
You can find the demo of the above regex in here.
const regex = /^\d+(?:\.$|\.\d+)?[KkMm]?$/gm;
const str = `400K
4.2.K
4.3K
3.2M
300000
4....K
4K
500.
300.K`;
let m;
while ((m = regex.exec(str)) !== null) {
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`${match}`);
});
}
Upvotes: 1
Reputation: 163217
About the pattern you tried
Note that you don't need {1}
. The character class [0-9km]
matches 1 of a char k
or m
or a digit 0-9. This way the possible digits to match could be 0-3 instead of 0-2.
Using the quantifier *
for the group makes it possbile to also match 400.25.22.22.22k
You could use this pattern to validate the examples. The [0-9]+
at the beginning of the pattern makes sure that there has to be at least a single digit present.
If you want to allow 500.
you could use:
^[0-9]+(?:(?:\.[0-9]{1,2})?[km]?|\.)$
Explanation
^
Start of string[0-9]+
Match 1+ digits(?:
Non capture group
(?:\.[0-9]{1,2})?
Match an optional decimal part with 2 digits[km]?
Match optional k
or m
|
Or\.
Match a single dot)$
End of stringlet pattern = /^[0-9]+(?:(?:\.[0-9]{1,2})?[km]?|\.)$/;
[
"400k",
"400.2k",
"4m",
"500000",
"500.",
"300.k",
"4.2.k",
".3k",
"4...k",
].forEach(s => console.log(s + " --> " + pattern.test(s)));
Another option is to only match the dot when not directly followed by k
or m
^[0-9]+(?:\.(?![km]))?\d*[km]?$
Upvotes: 1
Reputation: 75840
With alternation (never really the prettiest) it could be done like:
^\d+([km]|\.|\.\d+[km])?$
See the Online Demo
^
- Start string ancor.d+
- One or more digits.(
- Opening capturing group (you could use non-capturing).
[km]
- A single character "k" or "m".|
- Alternation (OR).\.?
- A literal dot.|
- Alternation (OR).\.\d+[km]
- A literal dot followed by at least one digit and a character "k" or "m".)?
- Close capturing group and make it optional$
- Start string ancor.Upvotes: 2