Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
Parser's generators solution in Clear category for Unix Match. Part 3 by veky
class Anything:
"""Matches 0 or more of any characters."""
def eat(self, what):
for start in range(1 + len(what)): yield what[start:]
class AnyOf:
"""AnyOf(seq) matches any single character of seq.
AnyOf(seq, False) matches any single character not in seq."""
def __init__(self, chars, true=True):
self.chars, self.true = list(chars), true
def eat(self, what):
if what:
start, *rest = what
if (start in self.chars) == self.true: yield rest
def chars_between(c1, c2):
for o in range(ord(c1), 1+ord(c2)): yield chr(o)
def sequence(ip):
current = next(ip)
positive = current != '!'
seq = set(current * positive)
while ...:
previous, current = current, next(ip)
if current == '-': seq.update(chars_between(previous, next(ip)))
elif current == ']': break
else: seq.add(current)
if seq: yield AnyOf(seq, positive)
elif positive: yield from map(AnyOf, '[]')
else: yield from map(AnyOf, '[!]')
def analyze(ip):
for char in ip:
if char == '*': yield Anything()
elif char == '?': yield AnyOf('', False)
elif char == '\\': yield AnyOf(next(ip))
elif char == '[': yield from sequence(ip)
else: yield AnyOf(char)
def matches(input, gadgets):
if not gadgets: return not input
first, *rest = gadgets
return any(matches(tail, rest) for tail in first.eat(input))
def unix_match(filename: str, pattern: str) -> bool:
return matches(filename, list(analyze(iter(pattern))))
July 9, 2018
Comments: