替换Python中的重叠正则表达式模式

rjjhvcjd  于 2023-03-11  发布在  Python
关注(0)|答案(3)|浏览(140)

我正在处理一个.ttl文件,我收到的文件是容易理解的,其中一个问题是rdfs:seeAlso的值没有被清理,它会破坏下游程序,我的意思是有如下形式的链接:

rdfs:seeAlso prefix:value_(discipline)

为了解决这个问题,我需要在特定字符前面加上\,根据RDF 1.1 Turtle文档,对于出现的字符,我需要转义以下字符:

_, ~, -, !, $, &, (, ), *, +, =, ?, #, %

一开始我认为这很容易,于是我开始构建一个re.sub()模式,尝试了很多可能的解决方案,但最接近的是:

re.sub(pattern=r"(rdfs\:seeAlso)(.{0,}?)([\_\~\-\!\$\&\(\)\*\+\=\?\#\%]{1})(.{0,})", repl='\\1\\2\\\\\\3\\4', string=str_of_ttl_file)

添加(rdfs\:seeAlso)组件是为了防止意外更改作为rdfs:labelrdfs:comment示例的字符串中的字符(即''""之间的任何上述字符)。
然而,这具有仅对第一次出现起作用的缺点,并且导致:

rdfs:seeAlso prefix:value\_(discipline)

它应该在的地方

rdfs:seeAlso prefix:value\_\(discipline\)

任何帮助或指导,这将是非常感谢!
编辑1:rdfs:labelrdfs:comment的示例是单引号(')或双引号(")之间的字符串,例如:

rdfs:label "example-label"@en

或者

rdfs:comment "This_ is+ an $example$ comment where n&thing should be replaced."@en

不需要替换其中的特殊字符,Turtle才能正常工作,因此正则表达式应将其保留。

9lowa7mx

9lowa7mx1#

首先,你不需要对模式中[...]内的字符进行转义(-应该是最后一个,否则in将被识别为range),这将使你的代码更具可读性,然后你可以在while循环中进行替换,并使用lookbehind来确保字符没有被转义:

import re

input_text = "rdfs:seeAlso prefix:value_(discipline)" 

pattern = re.compile(r"(rdfs:seeAlso.*?)(?<!\\)([_~!$&()*+=?#%-])")

repl_str = ''
while repl_str != input_text:
    repl_str = input_text
    input_text = re.sub(pattern, r'\1\\\2', repl_str)

print(input_text)

注意:对替换模式使用原始字符串会使其可读性更强
输出:

rdfs:seeAlso prefix:value\_\(discipline\)
yrdbyhpb

yrdbyhpb2#

我认为您应该分开检查字符串是否以rdfs:seeAlso和replacement开头。

str_of_ttl_file = "rdfs:seeAlso prefix:value_(discipline)"

if str_of_ttl_file.startswith('rdfs:seeAlso'):
    str_of_ttl_file = re.sub(r'([_~!$&()*+=?#%-])', r'\\\1', str_of_ttl_file)

print(str_of_ttl_file)
jexiocij

jexiocij3#

此解决方案 * 无需正则表达式 * 即可完成此操作:

def escape(inputstr, chars_to_escape):
    translation_dict = {c: '\\' + c for c in chars_to_escape}
    translation_table = str.maketrans(translation_dict)
    return inputstr.translate(translation_table)

def conditionalTurtleReplace(inputstr):
    if inputstr.startswith('rdfs:seeAlso'):
        return escape(inputstr, r'_~-!$&()*+=?#%')
    else:
        return inputstr

str1 = 'rdfs:seeAlso prefix:value_(discipline)'
str2 = 'rdfs:label "example-label"@en'
str3 = 'rdfs:comment "This_ is+ an $example$ comment where n&thing should be replaced."@en'
print(conditionalTurtleReplace(str1))
# output: rdfs:seeAlso prefix:value\_\(discipline\)
print(conditionalTurtleReplace(str2))
# output: rdfs:label "example-label"@en
print(conditionalTurtleReplace(str3))
# output: rdfs:comment "This_ is+ an $example$ comment where n&thing should be replaced."@en

相关问题