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

正则表达式:如何在Python中将LaTeX分数转换为可操作的表达式?,python,regex,latex,Python,Regex,Latex,我想创建一个解析器,它接受任何LaTeX格式的字符串,并返回Python可以计算的表达式 我对分数有几个问题。以下是一些示例: 乳胶(输入) 可互操作字符串(输出) \frac{1}{2} ((1)/(2)) \frac{x}{3b} ((x)/(3b)) \frac{2-m}{3} ((2-m)/(3)) \frac{7}{5+y} ((7)/(5+y)) 我不知道你为什么要采取两阶段的方法;正如您所注意到的,它会在第二阶段给您带来正则表达式元字符的问题。您可以使用re.sub,在匹配时进行替

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

我对分数有几个问题。以下是一些示例:

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

我不知道你为什么要采取两阶段的方法;正如您所注意到的,它会在第二阶段给您带来正则表达式元字符的问题。您可以使用
re.sub
,在匹配时进行替换:

重新导入
分数\u re=re.compile(r'\\frac{([^}]+)}{([^}]+)}
def解析器(表达式):
返回分数(r'(\1)/(\2)),表达式)
打印(解析器(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))

请注意,在正则表达式中使用
[^}]+
*?
更有效,因为它将减少回溯。

您可以在
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)

这个表达可以归结为

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

实际上,不需要使用命名组,只是为了清楚起见。

@Reti43查找分数不是问题所在。问题是把匹配项转换成格式:
((分子)/(分母))
我认为你的正则表达式应该是类似于
{[^}]+}
哇,这太简洁了!我知道我所做的有点低效,因为我的代码对字符串进行了两次检查。所以要明确的是,
\1
\2
是指第一组和第二组吗?@JacobStrauss。你可以使用Jan的答案中的命名组,但我认为这更容易。谢谢Nick!谢谢你花时间帮我:)@JacobStrauss别担心,我很高兴能帮上忙。简:这是一个极好的回答,谢谢你帮了我!我没有想到要使用lambda函数,命名组对我来说是新的。我学了很多,谢谢
\\frac\{(?P<numerator>[^{}]+)\}\{(?P<denominator>[^{}]+)\}