使用正则表达式捕获多种可能性

时间:2015-01-08 22:32:41

标签: python regex

我试图从reddit上的名单列表中提取多个名称,即

"Title: /u/foo, /u/bar"
"Title - /u/foo and /u/bar"
"title-/u/foo, /u/bar and /u/foobar"
"Title /u/barfoo (/u/foo and /u/bar)"

我无法在1到100之间匹配任意数量的名称。

编辑:我不认为我明确表示我提供的示例字符串是我正在搜索的实际文本的小片段。我正在检查/ r / KarmaCourt中帖子的正文,如下:

http://www.reddit.com/r/KarmaCourt/comments/1ifz0u/ http://www.reddit.com/r/KarmaCourt/comments/28hv73/

问题在于围绕构造正则表达式。我不想知道如何搜索我给名字的示例字符串。

我知道r'title.*/u/(\w{3:20})'将与该行中的姓氏相匹配,r'title.*?/u/(\w{3:20})'将与该行中的第一个匹配,并且我可以在末尾手动添加一些r'.*?/?u?/?(\w{3:20})?'表达式中的更多名称,但我不禁认为这是一种不好的方式。

r'title.*?(?=/u/\w{3:20})(.*)'获取匹配的字符串并从中拉出所有匹配的r'/u/(\w{3:20})'组会不会更好,或者有没有办法在一步中完成所有这些我从根本上失踪?

注意:这个项目是在python中完成的,但这更像是一个基本问题。

3 个答案:

答案 0 :(得分:1)

如果Python支持,您可以使用\G构造 \ G表示在最后一场比赛结束时开始搜索。

这基本上允许您限定新搜索的开始(在这种情况下为标题
没有实际检查每次。

然后进行全局搜索。每场比赛后,名称在第1组 我设置了多线修改器。如果您一次测试1行,则可能不需要。

 # (?mi)(?:(?!\A)\G|^Title).*?/u/(\w{3,20})

 (?xmi-)                       # Inline modifier = 
                               # expanded, multiline, case insensitive
 (?:
      (?! \A )                      # Not beginning of string
      \G                            # If matched before, start at end of last match
   |                              # or,
      ^ Title                       # BOL then 'title'
 )
 .*?                           # non-greedy any char's
 /u/                           # until '/u/'
 ( \w{3,20} )                  # (1), then 3 to 20 word characters

<强>附录
这是输出,将给出一个如何工作的想法。

输出

 **  Grp 0 -  ( pos 0 , len 13 ) 
Title: /u/foo  
 **  Grp 1 -  ( pos 10 , len 3 ) 
foo  

------------

 **  Grp 0 -  ( pos 13 , len 8 ) 
, /u/bar  
 **  Grp 1 -  ( pos 18 , len 3 ) 
bar  

------------

 **  Grp 0 -  ( pos 24 , len 14 ) 
Title - /u/foo  
 **  Grp 1 -  ( pos 35 , len 3 ) 
foo  

------------

 **  Grp 0 -  ( pos 38 , len 11 ) 
 and /u/bar  
 **  Grp 1 -  ( pos 46 , len 3 ) 
bar  

------------

 **  Grp 0 -  ( pos 52 , len 12 ) 
title-/u/foo  
 **  Grp 1 -  ( pos 61 , len 3 ) 
foo  

------------

 **  Grp 0 -  ( pos 64 , len 8 ) 
, /u/bar  
 **  Grp 1 -  ( pos 69 , len 3 ) 
bar  

------------

 **  Grp 0 -  ( pos 72 , len 14 ) 
 and /u/foobar  
 **  Grp 1 -  ( pos 80 , len 6 ) 
foobar  

------------

 **  Grp 0 -  ( pos 89 , len 15 ) 
Title /u/barfoo  
 **  Grp 1 -  ( pos 98 , len 6 ) 
barfoo  

------------

 **  Grp 0 -  ( pos 104 , len 8 ) 
 (/u/foo  
 **  Grp 1 -  ( pos 109 , len 3 ) 
foo  

------------

 **  Grp 0 -  ( pos 112 , len 11 ) 
 and /u/bar  
 **  Grp 1 -  ( pos 120 , len 3 ) 
bar  

答案 1 :(得分:0)

以下是如何在python中完成的。 findall将返回句子中匹配的单词列表。一旦你拥有它,你可以迭代它获取用户名。

import re

s = ["Title: /u/foo, /u/bar",
     "Title - /u/foo and /u/bar",
     "title-/u/foo, /u/bar and /u/foobar",
     "Title /u/barfoo (/u/foo and /u/bar)"]

for t in s:
    matches = re.findall(r'/u/(\w+)', t)
    print matches

答案 2 :(得分:0)

您真的不需要正则表达式,只需使用str.split()str.rstrip()

>>> l=["Title: /u/foo, /u/bar",
... "Title - /u/foo and /u/bar",
... "title-/u/foo, /u/bar and /u/foobar",
... "Title /u/barfoo (/u/foo and /u/bar)"]
>>> s=[i.split() for i in l]
>>> [[j.split('/u/')[1].rstrip(')') for j in i if '/u/' in j]for i in s]
[['foo,', 'bar'], ['foo', 'bar'], ['foo,', 'bar', 'foobar'], ['barfoo', 'foo', 'bar']]

如果你想使用正则表达式,你可以给我们一个positive look-behind

>>> import re
>>> s=[re.findall(r'(?<=/u/)\w+',i) for i in l]
>>> s
[['foo', 'bar'], ['foo', 'bar'], ['foo', 'bar', 'foobar'], ['barfoo', 'foo', 'bar']]