使用模式作为字典键

时间:2016-08-04 11:51:38

标签: python dictionary pattern-matching backslash

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

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路径,并使用反斜杠)感到头疼,主要是因为它被用作模式。

  • 字典定义:r'C:\\work\\l10n\\.'我转义反斜杠,因为该字符串将用作模式。
  • 如果我打印字典:C:\\\\work\\\\l10n\\\\.反斜杠出现双重转义,我理解,因为我将字符串定义为原始字符串。
  • 如果我走字典并打印键:C:\\work\\l10n\\.我完全看到我写的原始字符串。打印整个字典报告的字符串与打印单个字符串不同,这有点令人困惑,但我想这与“打印字典”的实现有关。
  • 我从文件中读到的内容:'C:\work\l10n\.'非转义反斜杠。
  • 我必须做什么才能将我从文件中读取的内容用作字典键:转义反斜杠,并将文本转换为C:\\work\\l10n\\.

这段代码能以某种方式简化吗?例如。所以我不需要通过代码逃避反斜杠?

1 个答案:

答案 0 :(得分:2)

您可以尝试以下方式:

>>> 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') vs matcher.group(0))< / p>

groupdict方法返回模式中的命名组及其匹配的值。因为模式是group1|group2|group3,所以只有一个组实际上会匹配;其他2将在None返回的dict中具有groupdict值(在我的示例中:match_value将是!=仅对于导致匹配的组而言是无)。

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