Python 中的递归正则表达式匹配平衡括号并替换

问题描述 投票:0回答:1

我有一些 LaTeX 源代码和一些注释:三种类型:

  • \ins{who}{what}
  • \rem{who}{what}
  • \rpl{who}{whatold}{whatnew}

目标是运行源文件并按以下方式替换所有出现的情况:

\ins{who}{what}->what
\rem{who}{what}->''
\rpl{who}{whatold}{whatnew}->whatnew

我最初的想法是

python
+
regex
但正如您在下面的示例中看到的,很快就会遇到平衡括号问题。根据here的讨论,我想出了替换为
\\rpl\{[a-z]{2}\}(\{((?>[^}{]+|(?1))*)\})(\{((?>[^}{]+|(?3))*)\})
的正则表达式,并替换为第四组。我在 regex101 上验证了 PCRE2。但我很难让它在 Python 中工作。

简单的测试是:

import regex

text = 'Velit sed ullamcorper morbi tincidunt ornare. Lorem dolor sed viverra ipsum nunc aliquet bibendum enim.\rpl{dd}{ Pellentesque \qtyrange{10}{20}{\celsius} habitant morbi \qtyrange{10}{20}{\celsius} tristique senectus \gls{abc}.}{Some new text with \qtyrange{10}{20}{\celsius} and more \gls{cdf}.}'
regx = r'\\rpl\{[a-z]{2}\}(\{((?>[^}{]+|(?1))*)\})(\{((?>[^}{]+|(?3))*)\})'

print(regex.findall(regx, text, overlapped=False))

测试的预期输出应该是:

'Velit sed ullamcorper morbi tincidunt ornare. Lorem dolor sed viverra ipsum nunc aliquet bibendum enim.Some new text with \qtyrange{10}{20}{\celsius} and more \gls{cdf}.'

在提到的讨论中,有些人建议不要使用正则表达式和实施括号计数。但我试图避免这种情况,我觉得当该工具存在并且似乎可以在其他风格中工作时,编程太多了。

有什么建议如何修改正则表达式或是否使用正则表达式之外的其他语言功能来做到这一点?正则表达式的优点是我可以轻松匹配周围的内容。

python regex recursion regex-group
1个回答
0
投票

这个正则表达式应该适用于使用 PyPi

regex
模块的递归括号匹配的所有 3 种情况:

rx = r'\\(ins|rpl|rem){[a-z]{2}}({((?>[^}{]+|(?2))*)}){1,2}'

正则表达式演示

代码:

import regex

text = r'Velit sed ullamcorper morbi tincidunt ornare. Lorem dolor sed viverra ipsum nunc aliquet bibendum enim.\rpl{dd}{ Pellentesque \qtyrange{10}{20}{\celsius} habitant morbi \qtyrange{10}{20}{\celsius} tristique senectus \gls{abc}.}{Some new text with \qtyrange{10}{20}{\celsius} and more \gls{cdf}.} and here is \ins{aa}{ins text with \qtyrange{20}{40}{\celsius} and more \gls{xyz}.} but we must ignore \rem{bb}{what} last part'

rx = regex.compile(r'\\(ins|rpl|rem){[a-z]{2}}({((?>[^}{]+|(?2))*)}){1,2}')

print (rx.sub(lambda m: m.group(3) if m.group(1) != 'rem' else '', text))

输出:

Velit sed ullamcorper morbi tincidunt ornare. Lorem dolor sed viverra ipsum nunc aliquet bibendum enim.Some new text with \qtyrange{10}{20}{\celsius} and more \gls{cdf}. and here is ins text with \qtyrange{20}{40}{\celsius} and more \gls{xyz}. but we must ignore  last part

请注意我们如何根据第一组更改 lambda 函数中的替换部分,即

ins
rpl
rem

代码演示

© www.soinside.com 2019 - 2024. All rights reserved.