两个字符串之间的正则表达式匹配?

19

我似乎找不到一种方法来提取所有注释,就像以下示例中的那样。

>>> import re
>>> string = '''
... <!-- one 
... -->
... <!-- two -- -- -->
... <!-- three -->
... '''
>>> m = re.findall ( '<!--([^\(-->)]+)-->', string, re.MULTILINE)
>>> m
[' one \n', ' three ']

由于正则表达式有误,two -- --所在的代码块不匹配。请问有哪位能够指导我如何提取两个字符串之间的内容。


大家在评论区提供的建议,我已经测试过了……现在这里是一个可行的解决方案,稍作升级。

>>> m = re.findall ( '<!--(.*?)-->', string, re.MULTILINE)
>>> m
[' two -- -- ', ' three ']
>>> m = re.findall ( '<!--(.*\n?)-->', string, re.MULTILINE)
>>> m
[' one \n', ' two -- -- ', ' three ']

谢谢!


3
任何在 [] 中的内容都代表一个单独的字符,因此 (-->) 不应作为一组来查找,这是问题的一部分。 - Joran Beasley
2
re.findall('<!--(.*?)-->', string, re.DOTALL) 就可以了。这里不需要 ^\(-->),因为问号使其非贪婪匹配。 - BrtH
你似乎只是在寻找这些单词?如果是这样,那么 m = re.findall('[\w]+', string, re.MULTILINE) 有什么问题吗?另外,string 是一个非常糟糕的名称,用于表示字符串。 - Ben
2个回答

38

这应该能解决问题。

 m = re.findall ( '<!--(.*?)-->', string, re.DOTALL)

1
如果有人想知道,“re.DOTALL”标志使点(.)匹配任何字符,包括换行符。 (.?)捕获括号内的文本,.?表示“非贪婪”版本的.*(即捕获最短的可能匹配)。 - Niko Pasanen
如果<!---->应该是结果列表项的一部分,则应删除捕获括号- re.findall('<!-.*?->',string,re.DOTALL) - Wiktor Stribiżew

3

一般情况下,使用正则语法无法在两个定界符之间进行任意匹配。

具体而言,如果允许嵌套,则

<!-- how do you deal <!-- with nested --> comments? -->

你可能会遇到问题。因此,虽然您可以使用正则表达式解决此特定问题,但是您编写的任何正则表达式都可以被某些奇怪的注释嵌套打破。
要解析任意注释,您需要转向解析无上下文语法的方法。一个简单的方法是使用推入自动机

2
我认为嵌套评论并不是很常见。如果其中的任何内容都被处理,那么这有点违背了评论的目的吧? - Anuj Gupta
1
看起来它们在HTML中是不可能的。https://dev59.com/CHRB5IYBdhLWcg3w-8Po 我会把这个留在这里,因为我认为这很重要,但我不指望得到任何赞同。 - Wilduck
1
有限状态机无法解析上下文无关文法 - 您可以使用下推自动机。 - James Thiele
@JamesThiele 啊啊啊,当然。我已经编辑了答案以反映这一点。 - Wilduck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接