Rewritten using regex.

This commit is contained in:
Guido van Rossum 1992-01-12 23:29:29 +00:00
parent 9542c58d45
commit 05e5219f53
1 changed files with 48 additions and 68 deletions

View File

@ -1,77 +1,57 @@
# module 'fnmatch' -- filename matching with shell patterns
# This version translates the pattern to a regular expression
# and moreover caches the expressions.
import os
import regex
cache = {}
def fnmatch(name, pat):
#
# Check for simple case: no special characters
#
if not ('*' in pat or '?' in pat or '[' in pat):
return name == pat
#
# Check for common cases: *suffix and prefix*
#
if pat[0] == '*':
p1 = pat[1:]
if not ('*' in p1 or '?' in p1 or '[' in p1):
start = len(name) - len(p1)
return start >= 0 and name[start:] == p1
elif pat[-1:] == '*':
p1 = pat[:-1]
if not ('*' in p1 or '?' in p1 or '[' in p1):
return name[:len(p1)] == p1
#
# General case
#
return fnmatch1(name, pat)
name = os.path.normcase(name)
pat = os.path.normcase(pat)
if not cache.has_key(pat):
res = translate(pat)
save_syntax = regex.set_syntax(0)
cache[pat] = regex.compile(res)
save_syntax = regex.set_syntax(save_syntax)
return cache[pat].match(name) == len(name)
def fnmatch1(name, pat):
def translate(pat):
i, n = 0, len(pat)
res = ''
while i < n:
c = pat[i]
if c == '*':
p1 = pat[i+1:]
if not ('*' in p1 or '?' in p1 or '[' in p1):
start = len(name) - len(p1)
return start >= 0 and name[start:] == p1
for i in range(i, len(name) + 1):
if fnmatch1(name[i:], p1):
return 1
return 0
elif c == '?':
if len(name) <= i : return 0
elif c == '[':
c, rest = name[i], name[i+1:]
i, n = i+1, len(pat) - 1
match = 0
exclude = 0
if i < n and pat[i] == '!':
exclude = 1
i = i+1
while i < n:
if pat[i] == c: match = 1
i = i+1
if i >= n or pat[i] == ']':
break
if pat[i] == '-':
i = i+1
if i >= n or pat[i] == ']':
break
if pat[i-2] <= c <= pat[i]:
match = 1
i = i+1
if i >= n or pat[i] == ']':
break
if match == exclude:
return 0
return fnmatch1(rest, pat[i+1:])
else:
if name[i:i+1] <> c:
return 0
i = i+1
# We don't get here if the pattern contained * or [...]
return i >= len(name)
def fnmatchlist(names, pat):
res = []
for name in names:
if fnmatch(name, pat): res.append(name)
if c == '*':
res = res + '.*'
elif c == '?':
res = res + '.'
elif c == '[':
j = i
if j < n and pat[j] == '!':
j = j+1
if j < n and pat[j] == ']':
j = j+1
while j < n and pat[j] != ']':
j = j+1
if j >= n:
res = res + '\\['
else:
stuff = pat[i:j]
i = j+1
if stuff[0] == '!':
stuff = '[^' + stuff[1:] + ']'
elif stuff == '^'*len(stuff):
stuff = '\\^'
else:
while stuff[0] == '^':
stuff = stuff[1:] + stuff[0]
stuff = '[' + stuff + ']'
res = res + stuff
elif c in '\\.+^$':
res = res + ('\\' + c)
else:
res = res + c
print 'translate(' + `pat` + ') == ' + `res`
return res