使用模式作为字典键

Using a pattern as a dictionary key

我正在尝试一次在一个文件中执行一组搜索和替换。为此,我使用了一个字典,其中要搜索的模式是键,替换文本是键值。我将所有替换编译成一个模式,并使用以下代码进行搜索替换:

re_compiled = re.compile("|".join(k for k in sub_dict))

# Pattern replacement inner function
def replacement_function(match_object):
    key = str(match_object.group(0))
    if key.startswith(r'C:\work\l10n'):
        key = key.replace("\", "\\")
        key = key[:-1] + '.'
    return sub_dict[key]

while 1:
    lines = in_f.readlines(100000)
    if not lines:
        break
    for line in lines:
        line = re_compiled.sub(replacement_function, line)
        out_f.write(line)

我定义字典如下:

g_sub_dict = {
                r'C:\work\l10n\.' : r'/ae/l10n/'
              , r'maxwidth="0"'      : r'maxwidth="-1"'
              , r'></target>'        : r'>#####</target>'
             }

我对第一个键(这是一个 Windows 路径,并使用反斜杠)有点头疼,主要是因为它被用作模式。

能否以某种方式简化此代码?例如。这样我就不需要通过代码转义反斜杠了?

您可以尝试类似的方法:

>>> text = r'start C:\work\l10n\. normal data maxwidth="0" something something ></target> end'
>>> # sub_dict format: {'symbolic_group_name': ['pattern', 'replacement']}
...
>>> sub_dict = {'win_path': [r'C:\work\l10n\.', r'/ae/l10n//'],
...             'max_width': [r'maxwidth="0"', r'maxwidth="-1"'],
...             'target': [r'></target>', r'>#####</target>']}
>>> p = re.compile("|".join('(?P<{}>{})'.format(k, v[0]) for k, v in sub_dict.items()))
>>> def replacement_function(match_object):
...   for group_name, match_value in match_object.groupdict().items():
...     if match_value:
...       # based on how the pattern is compiled 1 group will be a match
...       # when we find it, we return the replacement text
...       return sub_dict[group_name][1]
...
>>> new_text = p.sub(replacement_function, text)
>>> print(new_text)
start /ae/l10n// normal data maxwidth="-1" something something >#####</target> end
>>>

使用命名组允许您依靠简单的字符串在替换字典中进行查找,并且不需要对 \.

进行特殊处理

编辑:

关于正则表达式模式的更改:我更改了您的 a|b|c 模式以使用命名组。命名捕获组的语法为 (?P<name>pattern)。在功能上它与拥有 pattern 相同,但是拥有一个命名组允许使用组名从 Matcher 对象获取数据(例如:matcher.group('name')matcher.group(0)

groupdict 方法 returns 模式中的命名组和它们匹配的值。因为模式是 group1|group2|group3 实际上只有 1 组匹配;其他 2 将在 groupdict 返回的字典中有一个 None 值(用我在示例中的话来说:match_value 将是!= None 仅适用于导致的组比赛)。

好处是组名可以是任何纯字符串(最好是简单且与模式目的相关的字符串)并且不会导致 \ 转义问题。