11

I am trying to create a regex that matches percentage for marks

For example if we consider few percentages

1)100%
2)56.78%
3)56 78.90%
4)34.6789%

The matched percentages should be

100%
56.78%
34.6789%

I have made an expression "\\d.+[\\d]%" but it also matches for 56 78.90% which I don't want.

If anyone knows such expression please share

Nishant123
  • 1,968
  • 2
  • 26
  • 44

5 Answers5

21
\\d+(?:\\.\\d+)?%

This should do it for you.

For more stringent test use,

\b(?<!\.)(?!0+(?:\.0+)?%)(?:\d|[1-9]\d|100)(?:(?<!100)\.\d+)?%

See demo.

https://regex101.com/r/zsNIrG/2

vks
  • 67,027
  • 10
  • 91
  • 124
  • 1
    @DoNhuVy use `\d+(?:\.\d+)?%` there as it is not java spcific http://regexr.com/3aumq – vks May 06 '15 at 09:28
  • Thank you for the above explain. But I see your pattern still match: `56 78.90%`. Is there something wrong? – Vy Do May 06 '15 at 09:40
  • @DoNhuVy yes m not sure if OP wants it or not.A simple addtion of anchors will do it.`^\d+(?:\.\d+)?%$` with `m` flag – vks May 06 '15 at 09:42
  • @vks yes u are correct ,but if i pass alone 100 then it wont work – ashishSober Mar 22 '18 at 11:38
  • this includes minus numbers- have you got a suggestion for excluding any values prefixed with `-`? – Jamie Oct 11 '21 at 15:59
  • 1
    @Jamie a simple lookbehind should do it....'(?<!-)' – vks Oct 11 '21 at 16:03
5

You haven't double-escaped your dot, which means it's a wildcard for any character, including whitespace.

Use something like:

 ┌ integer part - any 1+ number of digits
 |   ┌ dot and decimal part (grouped)
 |   |┌ double-escaped dot
 |   ||  ┌ decimal part = any 1+ number of digits
 |   ||  |    ┌ 0 or 1 greedy quantifier for whole group
 |   ||  |    |
"\\d+(\\.\\d+)?%"

For instance:

String[] inputs = { "100%", "56.78%", "56 78.90%", "34.6789%" };
Matcher m = null;
for (String s: inputs) {
    m = p.matcher(s);
    if (m.find())
        System.out.printf("Found: %s%n", m.group());
}

Output

Found: 100%
Found: 56.78%
Found: 78.90%
Found: 34.6789%

Note

This still matches the 3rd input, but only the last part.

If you want the 3rd input to just not match, you can surround your pattern with input boundaries, such as ^ for start of input, and $ for end of input.

That would become: "^\\d+(\\.\\d+)?%$"

Or, you can simply invoke Matcher#matches instead of Matcher#find.

Next step

You may want to do something with the numerical value you're retrieving.

In this case, you can surround your pattern with a group ("(\\d+(\\.\\d+)?)%") and invoke either Double.parseDouble or new BigDecimal(...) on your back-reference:

  • Double.parseDouble(m.group(1))
  • new BigDecimal(m.group(1))
Mena
  • 47,782
  • 11
  • 87
  • 106
5

^((100)|(\d{1,2}(.\d*)?))%$

Check this regular expression here: https://regex101.com/r/Ou3mJI/2

You can use this regular expression. It is valid for:

  1. 0 to 100 inclusive
  2. With and without decimal places

Below are valid values:

100% is valid
99.802% is valid
98.7% is valid
57% is valid
0% is valid

This regular expression invalidates below values:

  1. Negative numbers
  2. Number > 100
  3. Number with spaces

Invalid value examples:

-1%
99.989%
101%
56 78.90%

Hope this will help!

Saurabh Gupta
  • 169
  • 2
  • 5
0

The RegEx \\d+(\\.?\\d+)?% would work.

Alvin Magalona
  • 771
  • 3
  • 13
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. – Robin May 06 '15 at 09:28
  • 2
    @Robin this does answer the question.Why do you think it doesnt? – vks May 06 '15 at 09:36
0

All credit goes to @vks for this answer, but I was looking for a regex that matched:

  • Positive values between 0% - 100%
  • No negative values
  • In any given string

This includes a negative lookahead (?<!-) which excludes minus numbers.

\b(?<!-)(?<!\.)(?!0+(?:\.0+)?%)(?:\d|[1-9]\d|100)(?:(?<!100)\.\d+)?%
Jamie
  • 3,105
  • 1
  • 25
  • 35