我正在尝试编写一个 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)[^\S\n]*(?=\S)')
print(p.sub(r'\1\n', 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
)
[^\S\n]* # eventual horizontal whitespaces
(?=\S) # followed by a non whitespace character
解释:如果你写这样的模式 (\\(?:begin|end)(?:{[^}]*}|\[[^]]*])*)[^\S\n]*(?=\S) 您无法阻止在下一个标记之前有换行符的情况。请参阅以下场景:
(\\(?:begin|end)(?:{[^}]*}|\[[^]]*])*)[^\S\n]*(?=\S) 匹配:
\begin{theorem}[Weierstrass Approximation]
\label{waapprox}
但是由于 (?=\S) 失败(因为下一个字符是换行符)回溯机制出现了:
(\\(?:begin|end)(?:{[^}]*}|\[[^]]*])*)[^\S\n]*(?=\S) 匹配:
\begin{theorem}[Weierstrass Approximation]
\label{waapprox}
和 (?=\S) 现在可以成功匹配 [ 字符。
原子组是一个非捕获组,它禁止在组中包含的子模式中进行回溯。表示法是 (?>subpattern)。不幸的是,re 模块没有此功能,但您可以使用技巧 (?=(subpattern))\1 来模拟它。
请注意,您可以使用 regex module (具有此功能)而不是 re:
import regex
p = regex.compile(r'(\\(?:begin|end)(?>(?:{[^}]*}|\[[^]]*])*)[^\S\n]*(?=\S)')
或
p = regex.compile(r'(\\(?:begin|end)(?:{[^}]*}|\[[^]]*])*+[^\S\n]*+(?=\S)')
