Python 在正则表达式匹配中插入字符串

Python 在正则表达式匹配中插入字符串,python,regex,string,match,Python,Regex,String,Match,我需要将字符串Special:MyLanguage/插入像[[ACBDEF]]这样的字符串,使其成为[[Special:MyLanguage/ABCDEF]] 问题是,我需要排除某些不应插入Special:MyLanguage/的匹配项: 已包含Special:MyLanguage/或 类别:或 文件:或 图像: 因此,用\[\[\[Special:MyLanguage/替换\[\[\[\[\[^(Special:MyLanguage | File:| Image:| Category:)]

我需要将字符串
Special:MyLanguage/
插入像
[[ACBDEF]]
这样的字符串,使其成为
[[Special:MyLanguage/ABCDEF]]

问题是,我需要排除某些不应插入
Special:MyLanguage/
的匹配项:

  • 已包含
    Special:MyLanguage/
  • 类别:
  • 文件:
  • 图像:

因此,用
\[\[\[Special:MyLanguage/
替换
\[\[\[\[\[^(Special:MyLanguage | File:| Image:| Category:)]
不起作用,因为它包含第一个字符(匹配项为
[[a
)。我已经阅读了很多教程,尝试过使用
$1
\G
之类的东西,但我还是有些挠头。

您可以使用负面前瞻来确保这些子字符串不会在
[[
之后立即出现:

(\[\[)(?!Special:MyLanguage/|File:|Image:|Category:)(.*?]])
并替换为
\1专用:MyLanguage/\2
。请参阅

详细信息

  • (\[\[)
    -组1:
    [[
    子字符串
  • (?!Special:MyLanguage/| File:| Image:| Category:)
    -在
    [[[/code>后面不能跟在替换组中列出的任何子字符串后面
  • (.*?]])
    -第2组:除换行符以外的任何0+字符,尽可能少,后跟
    ]]
:

输出:

[[Special:MyLanguage/text]]
[[File:text]]
[[Image:text]]
[[Category:text]]
[[Special:MyLanguage/Text and ]]
['[[Special:MyLanguage/ACBDEF]]', '[[Special:MyLanguage/ACBDEF]]', '[[Category:ACBDEF]]', '[[File:ACBDEF]]', '[[Special:MyLanguage/OneLasttest]]']

如果您不想弄乱正则表达式,这里有一个更简单的解决方案

exclusions = ["Special:MyLanguage/:","Category:","File:","Image:"]
# repl_str = "Special:MyLanguage/:"

def replace_str(str, repl_str):
    for ex in exclusions:
        if ex in str:
            return
    str = str[:2] + repl_str + str[2:]
假设它们都完全遵循您提供的模式:[[something]],并且它们将像您的问题一样插入


对于这样一个简单的例子,我发现正则表达式过于复杂,特别是在使用lookaheads、lookbehinds和使用捕获组时。尽可能地保持简单,节省算法复杂性,以便在真正需要的时候使用。你可以使用
re.sub
re.findall

import re
tests = ['[[ACBDEF]]', '[[Special:MyLanguage/ACBDEF]]', '[[Category:ACBDEF]]', '[[File:ACBDEF]]', '[[OneLasttest]]']
def isvalid(lang):
  return not re.findall('^Special:MyLanguage/|^File|^Category|^Image', lang)

final_results = [re.sub('(?<=\[\[)[\w\W]+(?=\]\])', '{}', i).format(*['Special:MyLanguage/'+c if isvalid(c) else c for c in re.findall('(?<=\[\[)[\w\W]+(?=\]\])', i)]) for i in tests]

将函数与
一起使用时排除

import re

excludes = ['Special:MyLanguage', 'Category:', 'File:', 'Image:']

s = "[[Special:MyLanguage/text]]\n[[File:text]]\n[[Image:text]]\n[[Category:text]]\n[[Text and ]]"

def analyze(match):
    for exclude in excludes:
        if exclude in match.group(1):
            return '[[{}]]'.format(match.group(1))
    return '[[Special:MyLanguage/{}]]'.format(match.group(1))

rx = re.compile(r'\[\[(.*?)\]\]')

s = rx.sub(analyze, s)
print(s)
这就产生了

[[Special:MyLanguage/text]]
[[File:text]]
[[Image:text]]
[[Category:text]]
[[Special:MyLanguage/Text and ]]

仅供参考,Python
re
不支持
\G
,替换的反向引用语法是
\n
\G
。我建议将
*?
编辑为
[^\]]*
使正则表达式尽可能安全。尽管OP dodn没有明确提到它,但他们正在编辑wikilinks,内容中不应该有括号(除非它是递归的,这是不可能的,但上面的正则表达式不会检查匹配的递归括号。)@Graham如果
[…]中没有
]
,是的,
[^]]*
效率更高。如果右侧分隔符是多字符字符串,而没有提供具体细节,我会使用延迟点匹配模式。
[[Special:MyLanguage/text]]
[[File:text]]
[[Image:text]]
[[Category:text]]
[[Special:MyLanguage/Text and ]]