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')
vsMatcher.group(0)
)
groupdict
方法返回模式中的命名组及其匹配的值。因为模式是group1 | group2 | group3
只有一个组实际匹配;其他2个将在由groupdict
返回的dict中有一个None
值(用我在示例中的话说:match\u value
将是!=仅对导致匹配的组无)
好处是组名可以是任何普通字符串(最好是简单的且与模式目的相关的字符串),并且不会导致
\
转义问题。您可以尝试使用文件位置的base64加密字符串吗?应该是一个更容易处理的键…谢谢@Alex,这可能是个好主意。Greate@flavius_st。作为一个说明,我编辑了我的问题,删除了我在/ae/l10n/'中注意到的额外“/”。但这完全不重要。现在回到你的解决方案,我觉得很有趣。请你再解释一下“编译”行(特别是模式
(?P{})`?非常感谢。@flavius\u st谢谢。结束这个问题,因为我已经有一段时间没有收到更多的答案了,这个答案对我来说很公平。