正则表达式用于匹配LaTeX公式

12

我正在尝试配置 TeXWorks 编辑器以使用与 TeXMaker 相同的语法着色。然而,TexWorks 使用正则表达式来指定应该着色的内容。不幸的是,它没有用于数学公式的默认设置。

我想匹配两个$之间的所有内容, 匹配两个\[\]之间的所有内容, 匹配两个\(\)之间的所有内容, 匹配两个$$$$之间的所有内容。后者在 LaTeX 文档中很少使用,所以不是非常必要。

可以使用多个正则表达式来匹配所有可能情况。

当然,\$会被转义,因此不希望匹配它,也不希望匹配 \\[ 等。

接下来,我还想匹配 \begin{equation}\end{equation} 之间的所有内容,但这很简单。

“无法完成”是一个可能的答案。


当编辑问题时,为什么答案和评论会消失? - marczellm
1
Oli根据你的批评删除了他的答案,因此它不再可见。关于你在那里发表的评论,\(…\)可以嵌套(考虑到完全有效的\(x = y + z \text{ where \(z\) is the error}\))。这是优先选择它而不是$…$的原因之一。但是,您可能想为简单起见忽略它。 - Konrad Rudolph
@KonradRudolph 没错,这不重要。 - marczellm
1个回答

14

尝试使用这个PCRE正则表达式:

(?<!\\)    # negative look-behind to make sure start is not escaped 
(?:        # start non-capture group for all possible match starts
  # group 1, match dollar signs only 
  # single or double dollar sign enforced by look-arounds
  ((?<!\$)\${1,2}(?!\$))|
  # group 2, match escaped parenthesis
  (\\\()|
  # group 3, match escaped bracket
  (\\\[)|                 
  # group 4, match begin equation
  (\\begin\{equation\})
)
# if group 1 was start
(?(1)
  # non greedy match everything in between
  # group 1 matches do not support recursion
  (.*?)(?<!\\)
  # match ending double or single dollar signs
  (?<!\$)\1(?!\$)|  
# else
(?:
  # greedily and recursively match everything in between
  # groups 2, 3 and 4 support recursion
  (.*(?R)?.*)(?<!\\)
  (?:
    # if group 2 was start, escaped parenthesis is end
    (?(2)\\\)|  
    # if group 3 was start, escaped bracket is end
    (?(3)\\\]|     
    # else group 4 was start, match end equation
    \\end\{equation\}
  )
))))

在此正则表达式中查看示例:https://regex101.com/r/wP2aV6/25

由于这个正则表达式使用了递归,所以它可以正确处理嵌套的数学表达式。

这仅适用于支持 PCRE 的正则表达式引擎。它需要一些高级功能的正则表达式引擎,例如负回顾后发断言、条件表达式和递归,这些功能并非所有正则表达式引擎都具备。

除非您只需要非常简单的内容,否则我建议不要使用此正则表达式,而是使用适当的 LaTeX 解析器。


很不幸,TeXWorks中的正则表达式引擎(可能是Qt的QRegEx)似乎不支持您所使用的一些功能。引用:[“回顾断言、独立子表达式和条件表达式不受支持”](http://doc.qt.digia.com/qt/qregexp.html)。我明白这些功能是必要的,所以看来我在这里运气不好。这与您的正则表达式无关,因为它本来就是正确的,所以感谢您的工作。 TeXWorks应该切换到另一个正则表达式引擎以支持数学高亮。 - marczellm
1
能否检测到以下内容:开头的$符号右侧必须紧跟一个字符,而结尾的$符号左侧必须紧跟一个字符。因此,$20,000和$30,000不会被解析为数学运算。所以我们可以有$20美元和$\sum_{i=1}^{\infty}$。 - jmlopez
你是不是指的是空格而不是字符? - Lodewijk Bogaards
这个答案对我帮助很大。不过,我发现一个小错误(即使在Regex101链接上也可以看到):多个内联方程式匹配得太贪婪了。例如,短语“变量$x$可以写成$y$”被匹配为“$x$可以写成$y$”。我更喜欢它匹配两次——$x$$y$——所以我改变了一行为(.*?(?R)?.*?)。最后注意,如果你在Ruby 1.9(或其他非PCRE衍生版本)中使用这个正则表达式,你可以将这一行重写为(.*?(\g<1>)?.*?) - user213345
我在使用以上代码在python中出现了“模式意外结束”的错误。 - Nitesh Verma
1
@NiteshVerma 确实,这个正则表达式需要递归匹配,而 Python 的正则表达式引擎不支持。您可以将递归去掉,并得到一个不支持嵌套表达式的可用解决方案。只需将 (.*?(?R)?.*?) 行替换为 (.*?) 即可。 - Lodewijk Bogaards

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接