107 lines · 2.9 KB · Python
RawDownload
"""Filename matching with shell patterns. fnmatch(FILENAME, PATTERN) matches according to the local convention.fnmatchcase(FILENAME, PATTERN) always takes case in account. The functions operate by translating the pattern into a regularexpression.  They cache the compiled regular expressions for speed. The function translate(PATTERN) returns a regular expressioncorresponding to PATTERN.  (It does not compile it.)""" import re __all__ = ["filter", "fnmatch","fnmatchcase","translate"] _cache = {} def fnmatch(name, pat):    """Test whether FILENAME matches PATTERN.     Patterns are Unix shell style:     *       matches everything    ?       matches any single character    [seq]   matches any character in seq    [!seq]  matches any char not in seq     An initial period in FILENAME is not special.    Both FILENAME and PATTERN are first case-normalized    if the operating system requires it.    If you don't want this, use fnmatchcase(FILENAME, PATTERN).    """     import os    name = os.path.normcase(name)    pat = os.path.normcase(pat)    return fnmatchcase(name, pat) def filter(names, pat):    """Return the subset of the list NAMES that match PAT"""    import os,posixpath    result=[]    pat=os.path.normcase(pat)    if not pat in _cache:        res = translate(pat)        _cache[pat] = re.compile(res)    match=_cache[pat].match    if os.path is posixpath:        # normcase on posix is NOP. Optimize it away from the loop.        for name in names:            if match(name):                result.append(name)    else:        for name in names:            if match(os.path.normcase(name)):                result.append(name)    return result def fnmatchcase(name, pat):    """Test whether FILENAME matches PATTERN, including case.     This is a version of fnmatch() which doesn't case-normalize    its arguments.    """     if not pat in _cache:        res = translate(pat)        _cache[pat] = re.compile(res)    return _cache[pat].match(name) is not None def translate(pat):    """Translate a shell PATTERN to a regular expression.     There is no way to quote meta-characters.    """     i, n = 0, len(pat)    res = ''    while i < n:        c = pat[i]        i = i+1        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].replace('\\','\\\\')                i = j+1                if stuff[0] == '!':                    stuff = '^' + stuff[1:]                elif stuff[0] == '^':                    stuff = '\\' + stuff                res = '%s[%s]' % (res, stuff)        else:            res = res + re.escape(c)    return res + "$"