如何在没有灾难性回溯的情况下在Python中用括号搜索和替换术语?

时间:2014-06-23 04:11:55

标签: python regex latex

我目前正在尝试查找这些术语(LaTeX定义)

\def\fB{\mathfrak{B}}

然后删除完整的字词\def\fB{\mathfrak{B}},并将\fB替换为\mathfrak{B}

我想出了以下RegEx:

curly = "(?:\{(?:.*)?\})"  # make sure that number of brackets is correct
target = "([^\{]*?"+curly+"*)"
search = r"(\\[A-Za-z][A-Za-z0-9]*)"
defcommand = re.compile(r"\\def" + search + "\{" + target + "+\}")

但是当我运行时,似乎发生了catastrophic backtracking,因为下面的最小(非)工作示例显示:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re

text = r"""
\newcommand*{\xindex}[1]{%
  \stepcounter{indexanchor}% make anchor unique
  \def\theindexterm{#1}%
  \edef\doindexentry{\noexpand\index
    {\expandonce\theindexterm|indexanchor{index-\theindexanchor}}}%
  \raisebox{\baselineskip}{\hypertarget{index-\theindexanchor}%
    {\doindexentry}}%
}


\def\fB{\mathfrak{B}}%Für Basis
\def\calS{\mathcal{S}}%Für Subbasis
\def\fT{\mathfrak{T}}%Für Topologie
\def\fU{\mathfrak{U}}%Für Topologie

\newlist{aufgabeenum}{enumerate}{1}
\setlist[aufgabeenum]{label=(\alph*),ref=\textup{\theaufgabe~(\alph*)}}
\crefalias{aufgabeenumi}{aufgabe}

% Commands for local abbreviations
"""


def print_matched_groups(m):
    print("number of groups: %i" % defcommand.groups)
    for i in range(defcommand.groups):
        print("group %i: %s" % (i, m.group(i)))
    print("done with print_matched_groups")

    curly = "(?:\{(?:.*)?\})"
    target = "([^\{]*?"+curly+"*)"
    search = r"(\\[A-Za-z][A-Za-z0-9]*)"
    defcommand = re.compile(r"\\def"+search+"\{"+target+"+\}")

for m in defcommand.finditer(text):
    print_matched_groups(m)
print("finished")

我怎么能

2 个答案:

答案 0 :(得分:0)

我刚刚找到了一个实用的解决方案。我知道嵌套不会很深,我可以使用这些信息来加速正则表达式:

curly = "(?:\{(?:.*)?\})"  # make sure that number of brackets is correct
target = "([^\{]*?"+curly+"{0, 3})"  # here is the change
search = r"(\\[A-Za-z][A-Za-z0-9]*)"
defcommand = re.compile(r"\\def" + search + "\{" + target + "+\}")

答案 1 :(得分:0)

而不是re模块,你需要使用regex module,这是无限优越的,并提供递归 - 你需要匹配Python中的嵌套结构。语法将相同,只有regex.some_method而不是re.the_same_method

这是一个curlies的递归正则表达式,可以在Python中使用regex模块:

{(?:[^{}]++|(?R))*}

您可以欣赏效果并参与this demo上的示例。

如果您有任何疑问,请与我们联系。 :)