1

I'm using the re module to validate IP address, this is my pattern:

"^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$"

Is there a way to know if a string can become a potential match without chaniging the pattern? for example: "127.0.0." is good or "10.0" however "10.." is not good. I don't mean the re.match function, I want to know if a string is not a match but it could be.

I need a function that will do something like this:

import re
p = re.potential("10.0","^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
print p # True

Edit: the thing is I want to know if I can recognize a potential match and use it to limit the wx.TextCtrl with the wx.EVT_CHAR Event, I didn't ask about my pattern. right now I have implemented it like this:

def OnChar(self,event):
    """event validation of ip"""
    key = event.GetKeyCode()
    text_value = event.GetEventObject().GetValue()
    length = len(text_value)
    numbers = True
    point = True

    if length:
        if length>2 and '.' not in text_value[-1:-4:-1]:
            numbers = False
        elif text_value[-1] =='.':
            point=False

    if Keys.is_numeric(key) and numbers:
        event.Skip()

    if Keys.equal(key,'.') and point:
        event.Skip()

    if Keys.is_moves(key):
        event.Skip()

This way the text the user enters can't be something not good, but is there a way to do it with the re module?

ori
  • 369
  • 2
  • 6
  • 17

2 Answers2

3

If I understand you correctly, you want an expression that matches when something can become an IP address, in a way. Just make parts optional:

^(?:\d{1,3}(?:\.\d{1,3}){0,2}(?:\.\d{0,3})?)?$

Demo: This matches 12, 234.54, 23.53.12.5 and the empty string, but not 34.34..4 or 3546.34.

edit: Less nested, thanks to Casimir et Hippolyte.

L3viathan
  • 26,748
  • 2
  • 58
  • 81
  • that's exactly what I meant. Is there a way to do it with Python or I need to modify all my regular expressions? I have also for mac address and more.. – ori May 10 '15 at 16:43
  • You can of course do this with python, just use my regex instead. – L3viathan May 10 '15 at 16:43
  • I meant without changing the pattern – ori May 10 '15 at 16:45
  • …why do you not want to change the pattern? Without changing it, I don't believe you can do it. There's no distinction between a partial match and a non-match. – L3viathan May 10 '15 at 16:50
  • [Actually, there appears to be a way](http://stackoverflow.com/a/25925157/1016216). I don't get why you would want to do that, though. – L3viathan May 10 '15 at 16:51
  • I am not well known with writing regex patterns, so I want to know if I can do this without changing all my regular expressions in my project – ori May 10 '15 at 16:53
  • Move all your identical regexes in one place and use variables everywhere else. That way changing it is easy. For now you can search-and-replace it, I guess. Otherwise look at my previous answer. But now you'll have to change things in many places anyways. – L3viathan May 10 '15 at 16:54
  • 2
    @ori This is a good answer. If you don't want to change anything then why use regex at all? This is easy enough without regex. – Shashank May 10 '15 at 17:18
  • 1
    For the particular case of an IP, you can write it too in "a less nested way": `^\d{1,3}(?:\.\d{1,3}){0,2}(?:\.\d{0,3})?$` – Casimir et Hippolyte May 10 '15 at 18:13
  • @CasimiretHippolyte good point! I just changed it to accept the empty string. – L3viathan May 10 '15 at 18:14
1

You can do that using re.match as

>>> if re.match(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", "10.0") :
...     print "Matched"
... else:
...     print "Not Matched"
... 
Not Matched
>>> if re.match(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", "127.0.0.0") :
...     print "Matched"
... else:
...     print "Not Matched"
... 
Matched

Note : The re.match function performs an entire search on the string, hence the anchors ^ and $ are safely omitted

nu11p01n73R
  • 26,397
  • 3
  • 39
  • 52