tags:

views:

136

answers:

6

I want to check a string that contains the period, ".", at most once in python.

A: 

While period is special char it must be escaped. So "\.+" should work.

EDIT:

Use '?' instead of '+' to match one or zero repetitions. Have a look at: re — Regular expression operations

Michał Niklas
That will match the period 1 or more times. I think the question wants 0 or 1 times.
Drew Noakes
You are right. In regexp plus means one or more. I should use question mark instead of plus.
Michał Niklas
+6  A: 
[^.]*\.?[^.]*$

And be sure to match, don't search

>>> dot = re.compile("[^.]*\.[^.]*$")
>>> dot.match("fooooooooooooo.bar")
<_sre.SRE_Match object at 0xb7651838>
>>> dot.match("fooooooooooooo.bar.sad") is None
True
>>>

Edit:

If you consider only integers and decimals, it's even easier:

def valid(s):
    return re.match('[0-9]+(\.[0-9]*)?$', s) is not None

assert valid("42")
assert valid("13.37")
assert valid("1.")
assert not valid("1.2.3.4")
assert not valid("abcd")
NicDumZ
Should you have a `^` at the start of the expression, or is that implied because you're matching?
Drew Noakes
it's implied, correct ;)
NicDumZ
+2  A: 

You can use:

re.search('^[^.]*\.?[^.]*$', 'this.is') != None

>>> re.search('^[^.]*\.?[^.]*$', 'thisis') != None
True
>>> re.search('^[^.]*\.?[^.]*$', 'this.is') != None
True
>>> re.search('^[^.]*\.?[^.]*$', 'this..is') != None
False

(Matches period zero or one times.)

Peter
A: 

If the period should exist only once in the entire string, then use the ? operator:

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

Breaking this down:

  1. ^ matches the beginning of the string
  2. [^.] matches zero or more characters that are not periods
  3. \.? matches the period character (must be escaped with \ as it's a reserved char) exactly 0 or 1 times
  4. [^.]* is the same pattern used in 2 above
  5. $ matches the end of the string

As an aside, personally I wouldn't use a regular expression for this (unless I was checking other aspects of the string for validity too). I would just use the count function.

Drew Noakes
Unless you ensure you match the *whole* string, this will match ".." (regex matches first period, and then finishes successfully without considering the second period).
Richard
True enough. Answer updated.
Drew Noakes
This will not cover the case when a string contains two periods with other letters between them.
davidi
@davidi - agreed, I've updated the answer and breakdown of the expression
Drew Noakes
+5  A: 

No regexp is needed, see str.count():

str.count(sub[, start[, end]])

Return the number of non-overlapping occurrences of substring sub in the range [start, end]. Optional arguments start and end are interpreted as in slice notation.

>>> "A.B.C.D".count(".")
3
>>> "A/B.C/D".count(".")
1
>>> "A/B.C/D".count(".") == 1
True
>>>
gimel
A: 

Why do you need to check? If you have a number in a string, I now guess you will want to handle it as a number soon. Perhaps you can do this without Looking Before You Leap:

try:
  value = float(input_str)
except ValueError:
  ...
else:
  ...
kaizer.se