我有一个要用于文本替换的前缀列表。每当我用对应的值替换整个匹配的文本时,我的程序就会工作,但如果我想保留匹配文本的一部分,而使用grouping替换其他部分则不行:
prefixes = {
r"http://www.w3.org/2002/07/owl#([a-z]+)": r"owl:\1",
r"http://www.w3.org/1999/02/22-rdf-syntax-ns#([a-z]+)": r"rdf:\1",
r"http://www.w3.org/2000/01/rdf-schema#([a-z]+)": r"rdfs:\1",
r"http://schema.org/": "schema",
r"http://www.w3.org/2001/XMLSchema#([a-z]+)": r"xsd:\1",
r"http://purl.org/linked-data/sdmx#([a-z]+)": r"sdmx:\1",
r"http://www.w3.org/XML/1998/namespace": r"xml"
}
# test = "http://www.w3.org/XML/1998/namespace" # works for this
test = "http://www.w3.org/2000/01/rdf-schema#a" # Does not work!
regex = re.compile("|".join(map(re.escape, prefixes.keys())))
test = regex.sub(lambda match:prefixes[match.group(0)], test)我想用"rdfs:a“替换test,但它不是这样工作的。我应该如何更改代码才能在这种情况下工作?
发布于 2020-04-22 03:55:53
你想要做的是非常复杂的。实际上,您不需要使用组和反向引用来简单地将匹配文本替换为另一个字符串,正如另一个答案所建议的那样。
但是,如果有任何原因导致简单方法不能正确识别您想要替换的字符串,并且组中的表达式对匹配很重要,那么下面的方法可以为您解决问题。
>>> prefixes = {
... 1: (r"http://www.w3.org/2002/07/owl#([a-z]+)", r"owl:\2"),
... 3: (r"http://www.w3.org/1999/02/22-rdf-syntax-ns#([a-z]+)", r"rdf:\4"),
... 5: (r"http://www.w3.org/2000/01/rdf-schema#([a-z]+)", r"rdfs:\6"),
... 7: (r"http://schema.org/", "schema"),
... 8: (r"http://www.w3.org/2001/XMLSchema#([a-z]+)", r"xsd:\9"),
... 10: (r"http://purl.org/linked-data/sdmx#([a-z]+)", r"sdmx:\11"),
... 12: (r"http://www.w3.org/XML/1998/namespace", r"xml")
... }
...
>>> test_1 = "http://www.w3.org/XML/1998/namespace"
>>> test_2 = "http://www.w3.org/2000/01/rdf-schema#a"
>>>
>>> expr = '(' + ')|('.join(p[0] for p in prefixes.values()) + ')'
>>>
>>> regex = re.compile(expr)
>>>
>>> regex.findall(test_2)
[('', '', '', '', 'http://www.w3.org/2000/01/rdf-schema#a', 'a', '', '',
'', '', '', '')]
>>> regex.sub(lambda m: m.expand(prefixes[m.lastindex][1]), test_2)
'rdfs:a'
>>> regex.sub(lambda m: m.expand(prefixes[m.lastindex][1]), test_1)
'xml'
>>> 那里!
以前的方法不起作用,因为匹配结果是动态确定的,不会与任何字典关键字匹配-字典关键字中有目标文本不会有的表达式。
所以问题是如何让一组表达式与一组替换字符串相关联,这些字符串中有对表达式中的组的反向引用。
我所做的是利用match对象的分组列表的结构来获得匹配表达式的索引。如果我使用括号使字典中的每个子表达式成为一个组,那么对于每个匹配,re.sub()都会生成一个match对象,其中包含许多组条目(请参阅regex.findall()行-它向您展示了匹配组列表的结构)。
匹配的子表达式在匹配对象列表中表示为带括号的子表达式位置处的非空字符串。
>>> expr = '(' + ')|('.join(p[0] for p in prefixes.values()) + ')'
>>> expr
'(http://www.w3.org/2002/07/owl#([a-z]+))|
(http://www.w3.org/1999/02/22-rdf-syntax-ns#([a-z]+))|
(http://www.w3.org/2000/01/rdf-schema#([a-z]+))|
(http://schema.org/)|
(http://www.w3.org/2001/XMLSchema#([a-z]+))|
(http://purl.org/linked-data/sdmx#([a-z]+))|
(http://www.w3.org/XML/1998/namespace)'
>>> regex.findall(test_2)
[('', '', '', '', 'http://www.w3.org/2000/01/rdf-schema#a', 'a', '', '',
'', '', '', '')]因此,我将prefixes数据结构修改为一个字典,它以m.lastindex返回的位置为关键字-这是匹配的带括号的子表达式的索引。
需要调整后向引用以与匹配列表中的位置对齐。例如,\1仅用于查找结果中的第一个匹配组。
我使用的match对象的另一个特性是m.expand()方法,它将反向引用转换为它们引用的组。
发布于 2020-04-22 04:34:03
有点框架挑战,但“为什么要为组而烦恼”?无论如何,您的正则表达式都不匹配行尾($),因此这里唯一的损失就是确保#之后的所有内容都以单个a-z字符开头:
import re
prefixes = {
r"http://www.w3.org/2002/07/owl#": r"owl:",
r"http://www.w3.org/1999/02/22-rdf-syntax-ns#": r"rdf:",
r"http://www.w3.org/2000/01/rdf-schema#": r"rdfs:",
r"http://schema.org/": "schema",
r"http://www.w3.org/2001/XMLSchema#": r"xsd:",
r"http://purl.org/linked-data/sdmx#": r"sdmx:",
r"http://www.w3.org/XML/1998/namespace": r"xml"
}
regex = re.compile("|".join(map(re.escape, prefixes.keys())))
test1 = "http://www.w3.org/XML/1998/namespace"
test2 = "http://www.w3.org/2000/01/rdf-schema#a"
assert regex.sub(lambda match:prefixes[match.group(0)], test1) == "xml"
assert regex.sub(lambda match:prefixes[match.group(0)], test2) == "rdfs:a"https://stackoverflow.com/questions/61263988
复制相似问题