Dave Smith
Dave Smith

Reputation: 69

regular expression to validate a pattern

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

Answers (3)

user7571182
user7571182

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.

Pictorial Representation

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.

Pictorial representation-2

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

The fourth bird
The fourth bird

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 string

Regex demo

let 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]?$

Regex

Upvotes: 1

JvdV
JvdV

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.

enter image description here

Upvotes: 2

Related Questions