Python:将格式字符串转换为正则表达式

标签 python regex formatting

我的应用程序的用户可以通过格式字符串配置某些文件的布局。

例如,用户指定的配置值可能是:

layout = '%(group)s/foo-%(locale)s/file.txt'

我现在需要找到所有已经存在的此类文件。使用 glob 模块似乎很容易:

glob_pattern = layout % {'group': '*', 'locale': '*'}
glob.glob(glob_pattern)

然而,困难的部分来了:给定 glob 结果列表,我需要获取与给定占位符匹配的所有文件名部分,例如所有不同的“语言环境”值。

我想我会为格式字符串生成一个正则表达式,然后我可以将其与 glob 结果列表进行匹配(或者可能会跳过 glob 并自己进行所有匹配)。

但我找不到一个很好的方法来创建具有正确组捕获和转义其余输入的正则表达式。

例如,这可能会给我一个匹配语言环境的正则表达式:

regex = layout % {'group': '.*', 'locale': (.*)}

但为了确保正则表达式有效,我需要通过 re.escape() 传递它,然后它也会转义我刚刚插入的正则表达式语法。首先调用 re.escape() 会破坏格式字符串。

我知道有 fnmatch.translate(),它甚至会给我一个正则表达式 - 但不能返回正确的组。

有没有一种好方法可以做到这一点,而不需要像用正则表达式安全的唯一值等替换占位符这样的黑客攻击?

是否可能有某种方式(可能是第三方库?)允许以更灵活的方式剖析格式字符串,例如在占位符位置拆分字符串?

最佳答案

由于您使用命名占位符,我将使用命名组。这似乎有效:

import re
UNIQ='_UNIQUE_STRING_'
class MarkPlaceholders(dict):
    def __getitem__(self, key):
        return UNIQ+('(?P<%s>.*?)'%key)+UNIQ

def format_to_re(format):
    parts = (format % MarkPlaceholders()).split(UNIQ)
    for i in range(0, len(parts), 2):
        parts[i] = re.escape(parts[i])
    return ''.join(parts)

然后进行测试:

>>> layout = '%(group)s/foo-%(locale)s/file.txt'
>>> print format_to_re(layout)
(?P<group>.*?)\/foo\-(?P<locale>.*?)\/file\.txt
>>> pattern = re.compile(format_to_re(layout))
>>> print pattern.match('something/foo-en-gb/file.txt').groupdict()
{'locale': 'en-gb', 'group': 'something'}

关于Python:将格式字符串转换为正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2654856/

相关文章:

python - 使用 Python3 读取 srt(字幕)文件

python - 如何将列表转换为字符串

javascript - 忽略字符串的第一个字符 - JS - 正则表达式

c# - 如何在 C# 中将字符串格式化为电话号码

python - 如何从 SQLAlchemy 中检索已执行的 SQL 代码

python - 从 mp4 python 下载 Youtube 音频

php - 正则表达式查找包含自定义符号的单词或句子

java - 我试图匹配日语字符的 Unicode 范围,但它抛出 PatternSyntaxException

php - 正则表达式 - 去除非数字并删除美分(如果有)

c# - 我需要 c# 中的一些东西,它像 c++ 中的 setw() 一样工作