Python 使用模式作为字典键

Python 使用模式作为字典键,python,dictionary,pattern-matching,backslash,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)

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

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>'
             }
g_sub_dict={
r'C:\\work\\l10n\\.:r'/ae/l10n/'
,r'maxwidth=“0”:r'maxwidth=“-1”
,r'>':r'>'
}
我对第一个键(它是一个Windows路径,使用反斜杠)有点头疼,主要是因为它被用作一个模式

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

这段代码可以简化吗?例如,这样我就不需要通过代码来逃避反斜杠了?

您可以尝试以下方法:

>>> 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
>>>
text=r'start C:\work\l10n\。正常数据maxwidth=“0”某物>结束' >>>#子目录格式:{'symbolic_group_name':['pattern','replacement']} ... >>>sub_dict={'win_path':[r'C:\\work\\l10n\\.',r'/ae/l10n/'], …'max_width':[r'maxwidth=“0”,r'maxwidth=“-1”], …目标:[r'>',r'>.']] >>>p=re.compile(“|”).join(“(?p{})”格式(k,v[0]),用于子目录项()中的k,v) >>>def替换功能(匹配对象): ... 对于组\名称,匹配\对象中的\值。groupdict().items(): ... 如果匹配_值: ... # 根据模式的编译方式,1组将是匹配的 ... # 当我们找到它时,我们返回替换文本 ... 返回子目录[组名称][1] ... >>>新文本=p.sub(替换函数,文本) >>>打印(新文本) start/ae/l10n//normal data maxwidth=“-1”something something>结束 >>> 使用命名组允许您依靠一个简单的字符串在替换字典中进行查找,并且不需要对
\
进行特殊处理

编辑:

关于regex模式的更改:我将a | b | c模式更改为使用命名组。命名捕获组的语法为
(?Ppattern)
。从功能上讲,它与具有
模式
相同,但具有命名组允许使用组名从
匹配器
对象获取数据(例如:
Matcher.group('name')
vs
Matcher.group(0)

groupdict
方法返回模式中的命名组及其匹配的值。因为模式是
group1 | group2 | group3
只有一个组实际匹配;其他2个将在由
groupdict
返回的dict中有一个
None
值(用我在示例中的话说:
match\u value
将是!=仅对导致匹配的组无)


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

您可以尝试使用文件位置的base64加密字符串吗?应该是一个更容易处理的键…谢谢@Alex,这可能是个好主意。Greate@flavius_st。作为一个说明,我编辑了我的问题,删除了我在
/ae/l10n/'中注意到的额外“/”。但这完全不重要。现在回到你的解决方案,我觉得很有趣。请你再解释一下“编译”行(特别是模式
(?P{})`?非常感谢。@flavius\u st谢谢。结束这个问题,因为我已经有一段时间没有收到更多的答案了,这个答案对我来说很公平。