Python regex for a number with or without decimal places, using a period or comma as a separator?

I am just learning regular expression, and now I'm trying to match a number that more or less represents this:

[zero or more numbers][possibly a dot or comma][zero or more numbers] 

No dots or commas are also good. Therefore, it must comply with the following:

 1 123 123. 123.4 123.456 .456 123, # From here it the same but with commas instead of dot separators 123,4 123,456 ,456 

But it should not match the following:

 0.,1 0a,1 0..1 1.1.2 100,000.99 # I know this and the one below are valid in many languages, but I simply want to reject these 100.000,99 

So far I have come up with [0-9]*[.,][0-9]* , but it does not work so well:

 >>> import re >>> r = re.compile("[0-9]*[.,][0-9]*") >>> if r.match('0.1.'): print 'it matches!' ... it matches! >>> if r.match('0.abc'): print 'it matches!' ... it matches! 

I have a feeling that I am doing two things wrong: I am using the match incorrectly and my regular expression is wrong. Can someone enlighten me on what I am doing wrong? All tips are welcome!

+9
source share
7 answers

Do you need to make the [.,] Part optional by adding ? after this character class, and also don't forget to add anchors. ^ claims that we are at the beginning, and $ claims that we are at the end.

 ^\d*[.,]?\d*$ 

Demo

 >>> import re >>> r = re.compile(r"^\d*[.,]?\d*$") >>> if r.match('0.1.'): print 'it matches!' ... >>> if r.match('0.abc'): print 'it matches!' ... >>> if r.match('0.'): print 'it matches!' ... it matches! 

If you do not want to resolve a single comma or period, use anticipation.

 ^(?=.*?\d)\d*[.,]?\d*$ 

Demo

+9
source

The problem is that you are requesting a partial match if it starts from the beginning.

One way is to end the regex in \Z (optional $ ).

\Z Matches only at the end of a line.

and the other instead of re.fullmatch .

 import re help(re.match) #>>> Help on function match in module re: #>>> #>>> match(pattern, string, flags=0) #>>> Try to apply the pattern at the start of the string, returning #>>> a match object, or None if no match was found. #>>> 

vs

 import re help(re.fullmatch) #>>> Help on function fullmatch in module re: #>>> #>>> fullmatch(pattern, string, flags=0) #>>> Try to apply the pattern to all of the string, returning #>>> a match object, or None if no match was found. #>>> 

Please note that fullmatch is new in 3.4.

You must also make the [.,] Part optional, so add ? to that.

'?' Makes the resulting RE match 0 or 1 repetitions of the previous RE. anyhow? will match either "a" or "ab".

Eg.

 import re r = re.compile("[0-9]*[.,]?[0-9]*\Z") bool(r.match('0.1.')) #>>> False bool(r.match('0.abc')) #>>> False bool(r.match('0123')) #>>> True 
+2
source

Your regex will work just fine if you just add a ^ in front and $ on the back so that the system knows how your line will begin and end.

try it

 ^[0-9]*[.,]{0,1}[0-9]*$ import re checklist = ['1', '123', '123.', '123.4', '123.456', '.456', '123,', '123,4', '123,456', ',456', '0.,1', '0a,1', '0..1', '1.1.2', '100,000.99', '100.000,99', '0.1.', '0.abc'] pat = re.compile(r'^[0-9]*[.,]{0,1}[0-9]*$') for c in checklist: if pat.match(c): print '%s : it matches' % (c) else: print '%s : it does not match' % (c) 1 : it matches 123 : it matches 123. : it matches 123.4 : it matches 123.456 : it matches .456 : it matches 123, : it matches 123,4 : it matches 123,456 : it matches ,456 : it matches 0.,1 : it does not match 0a,1 : it does not match 0..1 : it does not match 1.1.2 : it does not match 100,000.99 : it does not match 100.000,99 : it does not match 0.1. : it does not match 0.abc : it does not match 
+2
source

What about:

 (?:^|[^\d,.])\d*(?:[,.]\d+)?(?:$|[^\d,.]) 

If you do not want an empty string:

 (?:^|[^\d,.])\d+(?:[,.]\d+)?(?:$|[^\d,.]) 
+1
source
 ^(?=.?\d)(?!(.*?\.){2,})[\d.]+$|^(?=.?\d)(?!(.*?,){2,})[\d,]+$ 

Try this.Validates all cases.See demo.

http://regex101.com/r/hS3dT7/9

+1
source

Some ideas for checking non-empty matching:

1.) Using lookahead to check at least one digit:

 ^(?=.?\d)\d*[.,]?\d*$ 
  • From ^ start to $ end .
  • (?=.?\d) matches ,1 , 1 , ...
  • \d*[.,]?\d* Valid sequence: \d* any number of digits followed by one [.,] , \d*
  • Please note that first . inside lookahead is a metacharacter that denotes any character, while another inside the character class [.,] matches a literal .

Instead of a positive look, you can use a negative one: ^(?!\D*$)\d*[.,]?\d*$

Test in regex101 , Regular Expression Frequently Asked Questions


2.) Use 2 different templates:

 ^(?:\d+[.,]\d*|[.,]?\d+)$ 
  • (?: Starts a non-capture group to modify.
  • \d+[.,]\d* to match 1. , 1,1 , ... | OR
  • [.,]?\d+ to match 1 ,1 ...

Test in regex101

+1
source

If two decimal places are required, you can use the following:

 ^((\d){1,3},*){1,5}\.(\d){2}$ 

This will follow the following pattern:

  • 1.00
  • 10.00
  • 100.00
  • 1,000.00
  • 10.000.00
  • 100,000.00
  • 1,000,000.00
0
source

Source: https://habr.com/ru/post/976096/


All Articles