From 05e5219f53996f606b93fe42a56771819090e994 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Sun, 12 Jan 1992 23:29:29 +0000 Subject: [PATCH] Rewritten using regex. --- Lib/fnmatch.py | 116 ++++++++++++++++++++----------------------------- 1 file changed, 48 insertions(+), 68 deletions(-) diff --git a/Lib/fnmatch.py b/Lib/fnmatch.py index 549e0e7f018..c30aaca998b 100644 --- a/Lib/fnmatch.py +++ b/Lib/fnmatch.py @@ -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