teggy
teggy

Reputation: 6315

regex for character appearing at most once

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

Upvotes: 3

Views: 11821

Answers (6)

u0b34a0f6ae
u0b34a0f6ae

Reputation: 49803

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:
  ...

Upvotes: 0

Nicolas Dumazet
Nicolas Dumazet

Reputation: 7231

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

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")

Upvotes: 10

Drew Noakes
Drew Noakes

Reputation: 310907

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.

Upvotes: 0

gimel
gimel

Reputation: 86362

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
>>> 

Upvotes: 5

Michał Niklas
Michał Niklas

Reputation: 54302

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

Upvotes: 0

Peter
Peter

Reputation: 132227

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.)

Upvotes: 2

Related Questions