正则表达式:如何将LaTeX分数转换为Python中可操作的表达式?

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

我想创建一个解析器,它接受任何 LaTeX 格式的字符串并返回一个 Python 可以计算的表达式。

我在分数方面遇到了一些问题。以下是一些示例:

LaTeX(输入) 可互操作的字符串(输出)
\frac{1}{2}
((1)/(2))
\frac{x}{3b}
((x)/(3b))
\frac{2-m}{3}
((2-m)/(3))
\frac{7}{5+y}
((7)/(5+y))

这是我迄今为止尝试过的:

fraction_re = re.compile(r"\\frac{(.*?)}{(.*?)}")

def parser(expression):

    fractions = fraction_re.findall(expression)

    for numerator, denominator in fractions:
        pattern = r"\\frac\{%s\}\{%s\}" % (numerator, denominator)
        replace = f"(({numerator})/({denominator}))"
        expression = re.sub(pattern=pattern, repl=replace, string=expression)

    return expression

这对于情况一和情况二来说效果很好(见表),但对于情况三和情况四就有问题。我怀疑

-
+
符号引起了问题,因为它们本身就是正则表达式元字符。

我想添加一些额外的行来转义它们,例如

numerator = re.sub(pattern='+', repl='\+', string=numerator)

但这在我看来并不是一个好的长期策略。我还尝试向

pattern
变量添加方括号(因为方括号中的普通正则表达式符号不会被解释为这样),即

pattern = r"\\frac\{[%s]\}\{[%s]\}" % (numerator, denominator)

但这也不起作用。

接下来我可以尝试什么?

帖子脚本

我知道这个问题之前已经被问过很多次了(例如Python Regex to Simplify LaTex FractionsUsing Python Regex to Simplify Latex FractionsUsing if-then-else条件与Python正则表达式替换)但我觉得他们的问题与我的有点不同,我找不到对我有很大帮助的答案。

我也知道已经存在开箱即用的解析器可以完全满足我的要求(例如:https://github.com/augustt198/latex2sympy),但我真的很想构建这个我自己。

python regex latex
2个回答
1
投票

我不确定你为什么要采取两阶段方法;正如您所指出的,它会导致第二阶段的正则表达式元字符出现问题。您可以在匹配时使用

re.sub
:

进行替换
import re

fraction_re = re.compile(r'\\frac{([^}]+)}{([^}]+)}')

def parser(expression):
    return fraction_re.sub(r'((\1)/(\2))', expression)

print(parser(r'\frac{1}{2}  \frac{x}{3b}   \frac{2-m}{3}   \frac{7}{5+y}'))

输出

((1)/(2))  ((x)/(3b))   ((2-m)/(3))   ((7)/(5+y))

请注意,在正则表达式中使用

[^}]+
比使用
.*?
更有效,因为它会减少回溯。


1
投票

您可以在

re.sub()
中使用简单的 lambda 函数,如下所示:

import re

data = r"""
some very cool \textbf{Latex} stuff

\begin{enumerate}
\item even a very cool item
\end{enumerate}

Here comes the fun
\frac{1}{2} 
\frac{x}{3b}
\frac{2-m}{3}
\frac{7}{5+y}
"""

rx = re.compile(r'\\frac\{(?P<numerator>[^{}]+)\}\{(?P<denominator>[^{}]+)\}')

data = rx.sub(lambda m: f"(({m.group('numerator')}/({m.group('denominator')})", data)
print(data)

这会产生

some very cool \textbf{Latex} stuff

\begin{enumerate}
\item even a very cool item
\end{enumerate}

Here comes the fun
((1/(2)
((x/(3b)
((2-m/(3)
((7/(5+y)

这个表达式可以归结为

\\frac\{(?P<numerator>[^{}]+)\}\{(?P<denominator>[^{}]+)\}

确实不需要使用命名组,只是为了使其清晰可见。

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