Это кажется проще без регулярных выражений (хотя, возможно, существует более эффективный подход).
Преобразование строки в список символов (чтобы упростить подстановку символов при зацикливании), сохранение списка значений индекса открытых скобок, удаление значений индекса открытых скобок из списка, когда найдены совпадающие квадратные скобки, замените все закрывающие скобки, встречающиеся ранее соответствующую открытую скобку, замените все открытые скобки, оставшиеся в списке значений индекса после проверки всей строки, затем присоединитесь к списку, чтобы получить строку, содержащую замененные значения символов.
def unmatched(s):
chars = list(s)
opened = []
for i, c in enumerate(chars):
if c == '[':
opened.append(i)
if c == ']':
if not opened:
chars[i] = ']*UNMATCHED*'
else:
opened.pop()
for i in opened:
chars[i] = '*UNMATCHED*['
return ''.join(chars)
Пример вывода:
d = ['[[lang:foreign]', '[lang:foreign]]', '[[beep', '[beep', 'hello]', 'lang:foreign]']
for s in d:
print(unmatched(s))
# *UNMATCHED*[[lang:foreign]
# [lang:foreign]]*UNMATCHED*
# *UNMATCHED*[*UNMATCHED*[beep
# *UNMATCHED*[beep
# hello]*UNMATCHED*
# lang:foreign]*UNMATCHED*