使用模式作为字典键
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 路径,并使用反斜杠)有点头疼,主要是因为它被用作模式。
- 词典定义:
r'C:\work\l10n\.'
我转义了反斜杠,因为该字符串将用作模式。
- 如果我打印字典:
C:\\work\\l10n\\.
反斜杠出现双重转义,我理解,因为我将字符串定义为原始字符串。
- 如果我查字典并打印键:
C:\work\l10n\.
我会准确地看到我写的原始字符串。打印整个字典报告的字符串与打印单个键不同,这有点令人困惑,但我想这与 "print dictionary" 实现有关。
- 我从文件中读取的内容:
'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
>>>
使用命名组允许您依靠简单的字符串在替换字典中进行查找,并且不需要对 \
.
进行特殊处理
编辑:
关于正则表达式模式的更改:我更改了您的 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 仅适用于导致的组比赛)。
好处是组名可以是任何纯字符串(最好是简单且与模式目的相关的字符串)并且不会导致 \
转义问题。
我正在尝试一次在一个文件中执行一组搜索和替换。为此,我使用了一个字典,其中要搜索的模式是键,替换文本是键值。我将所有替换编译成一个模式,并使用以下代码进行搜索替换:
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\.
我会准确地看到我写的原始字符串。打印整个字典报告的字符串与打印单个键不同,这有点令人困惑,但我想这与 "print dictionary" 实现有关。 - 我从文件中读取的内容:
'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
>>>
使用命名组允许您依靠简单的字符串在替换字典中进行查找,并且不需要对 \
.
编辑:
关于正则表达式模式的更改:我更改了您的 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 仅适用于导致的组比赛)。
好处是组名可以是任何纯字符串(最好是简单且与模式目的相关的字符串)并且不会导致 \
转义问题。