views:

88

answers:

1

Hi all

I need to match two strings with simple wildcards:

"oh.my.*" matches "*.my.life", "oh.my.goodness" and "*.*.*", but not "in.my.house"

The only wildcard is *, which substitutes string of any character (minus .)

I thought of using fnmatch, but it does not accept wildcards in file name.

There is some code with regex which i am using now - something simpler would be better, i guess:

def notify(self, event, message):
    events = []
    r = re.compile(event.replace('.','\.').replace('*','[^\.]+'))
    for e in self._events:
        if r.match(e):
            events.append(e)
        else:
            if e.find('*')>-1:
                r2 = re.compile(e.replace('.','\.').replace('*','[^\.]+'))
                if r2.match(event):
                    events.append(e)
    for event in events:
        for callback in self._events[event]:
            callback(self, message)
+3  A: 

This should work for you:

def is_match(a, b):
    aa = a.split('.')
    bb = b.split('.')
    if len(aa) != len(bb): return False
    for x, y in zip(aa, bb):
        if not (x == y or x == '*' or y == '*'): return False
    return True

How it works:

  • First split the inputs on ..
  • If the arguments have a different number of components then fail immediately.
  • Otherwise iterate over the components and check for equality.
  • If either component is a * this also counts as a successful match.
  • If any component fails to match return False, otherwise return True.
Mark Byers
much cleaner and simpler. I am now testing performance, but i imagine that it will work much better than regex
ts
@ts: If performance is a serious concern and you want something slightly faster then there are still some options available. For example if one of the two parameters is the same for all the calls you could split it just once and passed the split array as a parameter instead of the original string.
Mark Byers
i made little optimisations. it seems that your method is +/- 2 times faster
ts
hmmm, here is a curious thought. what if one of the strings is shorter but the other one has '.*' suffix? say 'oh.my.*' and '*.my' - shouldn't those match?
Nas Banov
it should. Indeed, i modified Mark's code also to do that. it makes additional checks if len(aa) != len(bb) and therefore if any of them ends with '*'
ts