0

我想搜索出现在某个字符串之间的字符串。例如,

\start

\problem{number}
\subproblem{number}

/* strings that I want to get */

\subproblem{number}

/* strings that I want to get */

\problem{number}
\subproblem{number}
       ...
       ...
\end

更具体地说,我想获得问题编号和子问题编号以及答案之间的字符串。

我有点想出这样的表达方式

'(\\problem{(.*?)}\n)? \\subproblem{(.*?)} (.*?) (\\problem|\\subproblem|\\end)'

但它似乎不像我预期的那样工作。这个表达有什么问题?

4

3 回答 3

2

TeX 相当复杂,我不确定使用正则表达式解析它的感受。

也就是说,您的正则表达式有两个问题:

  • 您正在使用一个空格字符,您应该只使用所有空格
  • 您需要为最终组使用前瞻断言,这样它就不会被吃掉(因为下次您需要在正则表达式的开头匹配它)

试试这个:

>>> v
'\\start\n\n\\problem{number}\n\\subproblem{number}\n\n/* strings that I want to get */\n\n\\subproblem{number}\n\n/* strings that I want to get */\n\n\\problem{number}\n\\subproblem{number}\n       ...\n       ...\n\\end\n'
>>> re.findall(r'(?:\\problem{(.*?)})?\s*\\subproblem{(.*?)}\s*(.*?)\s*(?=\\problem{|\\subproblem{|\\end)', v, re.DOTALL)
[('number', 'number', '/* strings that I want to get */'), ('', 'number', '/* strings that I want to get */'), ('number', 'number', '...\n       ...')]
于 2013-01-26T01:22:14.327 回答
2

这个:

(?:\\problem\{(.*?)\}\n)?\\subproblem\{(.*?)\}\n+(.*?)\n+(?=\\problem|\\subproblem|\\end)

为我返回三个匹配项:

第一场比赛:

group 1: "number"
group 2: "number"
group 3: "/* strings that I want to get */"

比赛2:

group 1: null
group 2: "number"
group 3: "/* strings that I want to get */"

第 3 场比赛:

group 1: "number"
group 2: "number"
group 3: "       ...\n       ..."

但是,我宁愿分两步解析它。

首先使用以下方法找到问题的编号(第 1 组)和内容(第 2 组):

\\problem\{(.*?)\}\n(.+?)\\end

然后使用以下方法在该内容中找到子问题的编号(第 1 组)和内容(第 2 组):

\\subproblem\{(.*?)\}\n+(.*?)\n+(?=\\problem|\\subproblem|\\end)
于 2013-01-26T01:28:32.690 回答
2

如果问题真的是“这个表达式有什么问题?”,答案如下:

  • 您正在尝试将换行符与.*?. 你需要让它(?s)工作。
  • 您在正则表达式的中间有明确的空格和换行符,在源文本中没有任何对应的字符。你需要让它(?x)工作。

这可能不是表达式的全部错误。但只需添加(?sx),将其转换为原始字符串(因为我不相信自己可以正确混合 Python 引用和正则表达式引用),然后删除\n给我这个:

r'(?sx)(\\problem{(.*?)}? \\subproblem{(.*?)} (.*?)) (\\problem|\\subproblem|\\end)'

这将返回 2 个匹配而不是 0,这可能是对您的正则表达式的最小更改。

但是,如果问题是“我该如何解析这个?”,而不是“我现有的尝试有什么问题?”,我认为 impl 的解决方案更有意义(而且我也同意使用正则表达式解析 TeX 的观点通常一个坏主意)——或者,更好的是,像 Regexident 那样分两步完成。


如果使用正则表达式来解析 TeX 不是一个好主意,那么你会建议用什么方法来解析 TeX?

首先,作为一般的经验法则,如果我不能自己编写正则表达式来解决问题,我不想用正则表达式来解决它,因为我很难弄清楚它从现在开始的几个月。有时我将其分解为子表达式,或者使用(?x)注释并加载它,但通常我会寻找另一种方式。

更重要的是,如果你有一个真正的解析器,它可以使用你的语言并给你一棵树(或任何合适的东西),你可以走动和搜索——例如etreeXML——那么你就有了 90% 的解决方案。你在处理那种语言时会遇到的问题。一个又快又脏的正则表达式(尤其是一个你不能自己写的)只能让你解决下一个问题的 10%。而且通常情况下,如果我今天遇到问题,我会在接下来的几个月内遇到更多问题。

那么,在 Python 中什么是好的 TeX 解析器呢?老实说,我不知道。我知道scipy/matplotlib有一些东西可以做到这一点,所以我可能会先看看那里。除此之外,请查看 Google、PyPI,也许还有 tex.stackexchange.com。搜索中出现的第一件事是TexcallerplasTeX。我不知道它们有多好,或者它们是否适合您的用例,但是浏览教程并找出答案应该不会花很长时间。

如果事实证明那里什么都没有,而归结为自己写一些东西,例如pyparsing与正则表达式,那么这是一个更艰难的选择。某些语言,很容易只定义您关心的子集,而将其余部分保留为巨大的未解释标记,在这种情况下,真正的解析器将与正则表达式一样简单,因此您不妨这样做。其他语言,你必须处理一半的语法才能做任何有用的事情,所以我什至不会尝试。在决定走哪条路之前,我必须花一点时间来考虑它并尝试两种方式。

于 2013-01-26T01:28:54.147 回答