在Python中使用正则表达式解析LaTeX代码



我正在尝试编写一个Python脚本来整理我的LaTeX代码。我想找到启动环境的实例,但在下一个换行符之前的声明之后有非空白字符。例如,我想匹配

begin{theorem}[Weierstrass Approximation] label{wapprox}

但不匹配

begin{theorem}[Weierstrass Approximation] 
label{wapprox}

我的目标是在声明的结尾和第一个非空白字符之间插入一个换行符(使用re.sub)。粗略地说,我想找到像

这样的东西
(begin{evn}) ({text} | [text]) ({text2}|[text2]) ... ({textn}|textn]) (S)

做一个替换。我试着

expr = re.compile(r'\(begin|end){1}({[^}]+}|[[^]]+])+[^{[]+$',re.M)

,但这不是很有效。作为最后一组,它只匹配{,}或[,]的最后一对。

你可以这样做:

import re
s = r'''begin{theorem}[Weierstrass Approximation] label{wapprox}
but not match
begin{theorem}[Weierstrass Approximation] 
label{wapprox}'''
p = re.compile(r'(\(?:begin|end)(?=((?:{[^}]*}|[[^]]*])*))2)[^Sn]*(?=S)')
print(p.sub(r'1n', s))

模式细节:

(   # capture group 1
    \
    (?:begin|end)
    # trick to emulate an atomic group
    (?=(  # the subpattern is enclosed in a lookahead and a capture group (2)
        (?:{[^}]*}|[[^]]*])*
    ))  # the lookahead is naturally atomic
    2  # backreference to the capture group 2
)
[^Sn]* # eventual horizontal whitespaces
(?=S) # followed by a non whitespace character

解释:如果你写一个像(\(?:begin|end)(?:{[^}]*}|[[^]]*])*)[^Sn]*(?=S)这样的模式,你不能阻止在下一个标记之前有一个换行字符的情况。请看下面的场景:

(\(?:begin|end)(?:{[^}]*}|[[^]]*])*)[^Sn]* (?=S) matches:

begin{theorem}[Weierstrass Approximation]
label{wapprox}

但是由于(?=S)失败(因为下一个字符是换行符),出现了回溯机制:

(\(?:begin|end)(?:{[^}]*}|[[^]]*])* )[^Sn]*(?=S) matches:

begin{theorem} [Weierstrass Approximation]
label{wapprox}

(?=S)现在成功匹配[字符。

原子组是一个非捕获组,它禁止在组中包含的子模式中回溯。符号为(?>subpattern)。不幸的是,re模块没有这个功能,但是你可以用(?=(subpattern))1来模拟它。

请注意,您可以使用regex模块(具有此功能)来代替re:

import regex
p = regex.compile(r'(\(?:begin|end)(?>(?:{[^}]*}|[[^]]*])*)[^Sn]*(?=S)')

p = regex.compile(r'(\(?:begin|end)(?:{[^}]*}|[[^]]*])*+[^Sn]*+(?=S)')

最新更新