Python 通配符匹配&;替换和/或多个字符串通配符匹配

Python 通配符匹配&;替换和/或多个字符串通配符匹配,python,regex,wildcard,Python,Regex,Wildcard,我有两个非常相关的问题: 我想用通配符匹配字符串模式(即包含一个或多个“*”或“?”) 然后使用第二个通配符模式形成替换字符串。在这里,占位符应该引用相同的匹配子字符串 (例如在DOS copy命令中) 示例:pattern='*.txt'和replacement pattern='*.doc': 我想要aaa.txt-->aaa.doc和xx.txt.txt-->xx.txt.doc 理想情况下,它可以处理多个任意放置的通配符:例如,pattern='*.'和replacement patt

我有两个非常相关的问题:

  • 我想用通配符匹配字符串模式(即包含一个或多个“*”或“?”) 然后使用第二个通配符模式形成替换字符串。在这里,占位符应该引用相同的匹配子字符串 (例如在DOS copy命令中)

    示例:
    pattern='*.txt'
    replacement pattern='*.doc'
    : 我想要
    aaa.txt
    -->
    aaa.doc
    xx.txt.txt
    -->
    xx.txt.doc

    理想情况下,它可以处理多个任意放置的通配符:例如,
    pattern='*.'
    replacement pattern='XX*.'

    当然,需要应用一些约束(例如贪婪策略)。否则,诸如
    X*X*X
    之类的模式对于字符串
    XXXXXX
    不是唯一的

  • 或者,形成多重匹配。也就是说,我有一个或多个通配符模式,每个模式具有相同数量的通配符。每个模式与一个字符串匹配,但通配符应指向相同的匹配文本

    示例:
    pattern1='*.txt'
    pattern2='*-suffix.txt
    应匹配对
    string1='XX.txt'
    string2='XX-suffix.txt'
    ,但不匹配
    string1='XX.txt'
    string2='YY-suffix.txt'

    与第一个问题相比,这是一个定义更明确的问题,因为它避免了歧义问题,但可能非常类似

我相信这些任务都有算法,但是我找不到任何有用的算法


Python库有
fnmatch
,但这不支持我想做的事情。

有很多方法可以做到这一点,但我提出了以下方法,这应该适用于您的第一个问题。根据你的例子,我假设你不想匹配空格

此函数将第一个传递的模式转换为正则表达式,并将传递的替换模式转换为适用于
re.sub
函数的字符串

import re

def replaceWildcards(string, pattern, replacementPattern):
    splitPattern = re.split(r'([*?])', pattern)
    splitReplacement = re.split(r'([*?])', replacementPattern)
    if (len(splitPattern) != len(splitReplacement)):
        raise ValueError("Provided pattern wildcards do not match")
    reg = ""
    sub = ""
    for idx, (regexPiece, replacementPiece) in enumerate(zip(splitPattern, splitReplacement)):
        if regexPiece in ["*", "?"]:
            if replacementPiece != regexPiece:
                raise ValueError("Provided pattern wildcards do not match")
            reg += f"(\\S{regexPiece if regexPiece == '*' else ''})" # Match anything but whitespace
            sub += f"\\{idx + 1}" # Regex matches start at 1, not 0
        else:
            reg += f"({re.escape(regexPiece)})"
            sub += f"{replacementPiece}"
    return re.sub(reg, sub, string)
样本输出:

replaceWildcards("aaa.txt xx.txt.txt aaa.bat", "*.txt", "*.doc")
# 'aaa.doc xx.txt.doc aaa.bat'

replaceWildcards("aaa10.txt a1.txt aaa23.bat", "a??.txt", "b??.doc")
# 'aab10.doc a1.txt aaa23.bat'

replaceWildcards("aaa10.txt a1-suffix.txt aaa23.bat", "a*-suffix.txt", "b*-suffix.doc")
# 'aaa10.txt b1-suffix.doc aaa23.bat'

replaceWildcards("prefix-2aaa10-suffix.txt a1-suffix.txt", "prefix-*a*-suffix.txt", "prefix-*b*-suffix.doc")
# 'prefix-2aab10-suffix.doc a1-suffix.txt

注意f字符串需要Python>=3.6。

太好了。构建正则表达式并使用
re.sub
是个好主意。我做了一些微调(使用.而不是\S来匹配空白,只使用“^”和“$”匹配完整字符串,并对替换件进行斜杠转义
sub
part),效果非常好。