Python 正则表达式如何获取中间字符串
我想搜索出现在某个字符串之间的字符串。比如说,Python 正则表达式如何获取中间字符串,python,regex,Python,Regex,我想搜索出现在某个字符串之间的字符串。比如说, \start \problem{number} \subproblem{number} /* strings that I want to get */ \subproblem{number} /* strings that I want to get */ \problem{number} \subproblem{number} ... ... \end 更具体地说,我想得到问题编号和子问题编号,以及答案之
\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)'
但它似乎不像我预期的那样有效。这个表达式有什么问题?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 ...')]
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 ...')]
这个:
(?:\\problem\{(.*?)\}\n)?\\subproblem\{(.*?)\}\n+(.*?)\n+(?=\\problem|\\subproblem|\\end)
为我返回三个匹配项:
匹配1:
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): 然后使用以下方法查找子问题的编号(组1)和内容(组2):
\\subproblem\{(.*?)\}\n+(.*?)\n+(?=\\problem|\\subproblem|\\end)
这个:
(?:\\problem\{(.*?)\}\n)?\\subproblem\{(.*?)\}\n+(.*?)\n+(?=\\problem|\\subproblem|\\end)
为我返回三个匹配项:
匹配1:
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): 然后使用以下方法查找子问题的编号(组1)和内容(组2):
\\subproblem\{(.*?)\}\n+(.*?)\n+(?=\\problem|\\subproblem|\\end)
如果问题真的是“这个表达式有什么问题?”,那么答案如下:
- 您正在尝试将换行符与
匹配。你需要*?
才能让它工作(?s)
- 在正则表达式中间没有显式的空格和换行,在源文本中没有任何对应的字符。你需要
才能让它工作(?x)
(?sx)
,将其转换为原始字符串(因为我不相信自己能够正确地混合Python引用和正则表达式引用),然后删除\n
就可以得到以下结果:
r'(?sx)(\\problem{(.*?)}? \\subproblem{(.*?)} (.*?)) (\\problem|\\subproblem|\\end)'
这将返回2个匹配项而不是0,这可能是对正则表达式进行的最小更改
然而,如果问题是“我如何解析这个?”,而不是“我现有的尝试有什么问题?”,我认为impl的解决方案更有意义(我也同意使用regex解析TeX通常是个坏主意的观点)——或者,更好的是,像Regexident那样分两步进行
如果使用regex解析TeX不是一个好主意,那么您会建议使用什么方法来解析TeX 首先,作为一般的经验法则,如果我不能自己编写正则表达式来解决问题,我不想用正则表达式来解决它,因为几个月后我将很难弄明白它。有时我会将它分解成子表达式,或者使用
(?x)
并用注释加载它,但通常我会寻找另一种方法
更重要的是,如果您有一个真正的解析器,它可以使用您的语言,并为您提供一棵树(或任何合适的树),您可以像对待XML一样行走和搜索,例如etree
for XML,那么对于您在处理该语言时遇到的每一个问题,您都有90%的解决方案。一个快速而肮脏的正则表达式(特别是一个你不能自己写的正则表达式)只能让你解决下一个问题的10%。通常情况下,如果我今天有问题,我会在接下来的几个月里有更多的问题
那么,Python中TeX的好解析器是什么?老实说,我不知道。我知道scipy
/matplotlib
有一些功能,所以我可能会先看看。除此之外,请查看谷歌、PyPI,也许还有tex.stackexchange.com。搜索中首先出现的是和。我不知道它们有多好,也不知道它们是否适合您的用例,但浏览教程并找出答案应该不会花太长时间
如果结果是什么都没有,归结到自己写东西,比如vs.regex,那么这是一个更艰难的选择。在某些语言中,很容易只定义您关心的子集,而将其余部分作为巨大的未解释标记,在这种情况下,真正的解析器将与正则表达式一样简单,因此您不妨这样做。在其他语言中,在做任何有用的事情之前,你必须处理一半的语法,所以我甚至不会尝试。在决定走哪条路之前,我必须花一点时间来考虑它,并尝试两种方法。如果问题真的是“这个表达式有什么问题?”,下面是答案:
- 您正在尝试将换行符与
匹配。你需要*?
才能让它工作(?s)
- 在正则表达式中间没有显式的空格和换行,在源文本中没有任何对应的字符。你需要
才能让它工作(?x)
(?sx)
,将其转换为原始字符串(因为我不相信自己能够正确地混合Python引用和正则表达式引用),然后删除\n
就可以得到以下结果:
r'(?sx)(\\problem{(.*?)}? \\subproblem{(.*?)} (.*?)) (\\problem|\\subproblem|\\end)'
这将返回2个匹配项而不是0,这可能是对正则表达式进行的最小更改
然而,如果问题是“我如何解析它?”,而不是“我现有的尝试有什么问题?”,我认为impl的解决方案