【发布时间】:2016-08-12 11:16:57
【问题描述】:
我需要在文本中找到匹配项并获取其位置。例如,我必须在文本中找到“hello hello”。当文本是“hello hello world hello hello”时,没关系,我得到的位置是 0-11 和 18-29。但是当文本是“hello hello hello world”时,我只得到一个位置 - 0-11。但我必须找到两个(0-11 和 6-17)。我的意思是,我明白了
- 你好你好你好世界
但必须得到
你好你好你好世界
你好你好你好世界
在另一种情况下,我必须找到复杂的模式:“hello 1,2 beautiful 2,4 world”——这意味着“hello”和“beautiful”这两个词之间可能是一两个词,而两个词之间是“美丽”和“世界”2、3或4个字。我必须找到所有的组合。
这是模式:re.compile(u'(^|[\[\]\/\\\^\$\.\|\?\*\+\(\)\{\} !<>:;,#@])(hello)(([\[\]\/\\^\$\.\|\?\*\+\(\)\{\} !<>:;,#@%]+[a-zA-Zа-яА-Я$]+(-[a-zA-Zа-яА-Я$]+)*){1,2}[\[\]\/\\^\$\.\|\?\*\+\(\)\{\} !<>:;,#@%]*)(beautiful)(([\[\]\/\\^\$\.\|\?\*\+\(\)\{\} !<>:;,#@%]+[a-zA-Zа-яА-Я$]+(-[a-zA-Zа-яА-Я$]+)*){2,4}[\[\]\/\\^\$\.\|\?\*\+\(\)\{\} !<>:;,#@%]*)(world)($|[\[\]\/\\\^\$\.\|\?\*\+\(\)\{\} !<>:;,#@])')
而文字是“你好非常美丽美丽非常大的世界世界”。我可以得到唯一的一个组合,但需要得到 4 个:
你好非常美丽美丽非常大世界世界
你好非常美丽美丽非常大世界世界
你好非常美丽美丽非常大的世界世界
你好非常美丽美丽世界很大世界
当匹配项相互交叉时,如何获取匹配项的所有组合?
标志 re.DOTALL 没有帮助。
import re
patterns = [
u'(hello)(( [a-z]+ *){1,2})(beautiful)(( [a-z]+ *){2,4})(world)',
u'hello hello'
]
text = u'hello hello hello world hello very beautiful beautiful very big world world'
for p in patterns:
print p
c = re.compile(p, flags=re.I+re.U)
for m in c.finditer(text):
print m.start(), m.end()
结果是
>>> (hello)(( [a-z]+ *){1,2})(beautiful)(( [a-z]+ *){2,4})(world)
>>> 24 69
(need 24 69 and 24 69 and 24 75 and 24 75 - because there are two positions of the word "beautiful")
>>> hello hello
>>> 0 11
(need 0 11 and 6 17)
模式的真实例子是:
u"выйдите на улицы", u"избавить.* от", u"смотрите смотрите", u"смеят.*"
还有距离:
имени 0,3 ленина
целых 0,5 лет.*
целых 0,5 лет.* 0,1 назад
UPD
变体u'(?=(hello hello)) 有助于在单词之间没有距离的模式。但是如何在有距离的模式中使用它,例如(hello) (?:[a-zA-Zа-яА-Я]+ ){1,2}(beautiful) (?:[a-zA-Zа-яА-Я]+ ){2,4}(world)?
【问题讨论】:
-
IMO 如果您的正则表达式看起来像这样,那么您可能应该选择另一种模式,或者可能跳过通过正则表达式执行它。
-
问题不在当前的正则表达式中。它可以更简单,但问题不会消失。
-
如果模式不重要,请举一个 simple 和 small 示例,这样冗长而不清楚的问题会围绕您的实际问题产生烟幕跨度>