我正在尝试编写一个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)')