Python 正则表达式分组不是预期的
我有下面的正则表达式,它应该可以拉出3个组Python 正则表达式分组不是预期的,python,regex,Python,Regex,我有下面的正则表达式,它应该可以拉出3个组 ^(ser-num.*|\[ser-num.*])(?: )?(\w+)?(?: )?(http://.*\.com/(?:s(?:erial)?|p(?:roduct)?)/\d+(?:/)?(?:\d+|(?:\w|-)+)?) 这两个字符串: strings = [ "ser-num recommend http://example.com/s/123456 ", "ser-num http://example.com/s/12
^(ser-num.*|\[ser-num.*])(?: )?(\w+)?(?: )?(http://.*\.com/(?:s(?:erial)?|p(?:roduct)?)/\d+(?:/)?(?:\d+|(?:\w|-)+)?)
这两个字符串:
strings = [
"ser-num recommend http://example.com/s/123456 ",
"ser-num http://example.com/s/123456 ",
]
当我对正则表达式运行这些时,我收到以下组:
('ser-num recommend ', None, 'http://example.com/s/123456')
('ser-num ', None, 'http://example.com/s/123456')
为什么我的第一个结果是将“推荐”组合到组\1
,而不是\2
这是我的整个示例脚本:
import re
p = re.compile("""^(ser-num.*|\[ser-num.*])(?: )?(\w+)?(?: )?(http://.*\.com/(?:s(?:erial)?|p(?:roduct)?)/\d+(?:/)?(?:\d+|(?:\w|-)+)?)""")
strings = [
"ser-num recommend http://example.com/s/123456 ",
"ser-num http://example.com/s/123456 ",
]
for s in strings:
m = p.match(s)
try:
print m.groups()
except AttributeError:
print "Not a match for %s" % (s)
我的正则表达式的值表示可选组\2
确实存在
根据评论更新:
如果我使用这个正则表达式
^(ser-num.*|\[ser-num.*])\s?(\w*)\s?(http://.*\.com/(?:s(?:erial)?|p(?:roduct)?)/\d+(?:/)?(?:\d+|(?:\w|-)+)?)
我收到这些结果(注意组\2
中的空字符串而不是None
)
我建议使用以下regexp:
^(\[?ser-num\S*]?)\s*(\w*)\s*(http://.*\.com/(?:s(?:erial)?|p(?:roduct)?)/\d+(?:/)?(?:\d+|(?:\w|-)+)?)
这(特别是取代
*
的\S*
)强制(\w*)
位于其自己的捕获组中,而不是被第一个ser-num.*
字符组吞噬。请注意,第一组中的额外空格也是出于同样的原因,也就是说,它们被贪婪地捕获,而不是作为可选的匹配被丢弃。我建议使用以下regexp:
^(\[?ser-num\S*]?)\s*(\w*)\s*(http://.*\.com/(?:s(?:erial)?|p(?:roduct)?)/\d+(?:/)?(?:\d+|(?:\w|-)+)?)
这(特别是取代
*
的\S*
)强制(\w*)
位于其自己的捕获组中,而不是被第一个ser-num.*
字符组吞噬。请注意,第一组中的额外空格也是出于同样的原因,也就是说,它们被贪婪地捕获,而不是作为可选的匹配被丢弃。我建议使用以下regexp:
^(\[?ser-num\S*]?)\s*(\w*)\s*(http://.*\.com/(?:s(?:erial)?|p(?:roduct)?)/\d+(?:/)?(?:\d+|(?:\w|-)+)?)
这(特别是取代
*
的\S*
)强制(\w*)
位于其自己的捕获组中,而不是被第一个ser-num.*
字符组吞噬。请注意,第一组中的额外空格也是出于同样的原因,也就是说,它们被贪婪地捕获,而不是作为可选的匹配被丢弃。我建议使用以下regexp:
^(\[?ser-num\S*]?)\s*(\w*)\s*(http://.*\.com/(?:s(?:erial)?|p(?:roduct)?)/\d+(?:/)?(?:\d+|(?:\w|-)+)?)
这(特别是取代
*
的\S*
)强制(\w*)
位于其自己的捕获组中,而不是被第一个ser-num.*
字符组吞噬。请注意,由于同样的原因,您在第一个组中获得了额外的空格,即它们被贪婪地捕获,而不是作为可选的匹配被丢弃。单词推荐
是第一个组的一部分,因为它匹配部分regexpser-num.
。星形运算符返回可能最长的匹配。如果想要最短的匹配,请使用*?
试试这个:
p = re.compile("""^(ser-num.*?|\[ser-num.*?])(?: )?(\w+)?(?: )?(http://.*\.com/(?:s(?:erial)?|p(?:roduct)?)/\d+(?:/)?(?:\d+|(?:\w|-)+)?)""")
注意使用非贪婪星型:ser-num.*?
参考:
- 此处的
,*?
,+?
条目:??
推荐
属于第一组,因为它与部分regexpser-num.*
匹配。星形运算符返回可能最长的匹配。如果想要最短的匹配,请使用*?
试试这个:
p = re.compile("""^(ser-num.*?|\[ser-num.*?])(?: )?(\w+)?(?: )?(http://.*\.com/(?:s(?:erial)?|p(?:roduct)?)/\d+(?:/)?(?:\d+|(?:\w|-)+)?)""")
注意使用非贪婪星型:ser-num.*?
参考:
- 此处的
,*?
,+?
条目:??
推荐
属于第一组,因为它与部分regexpser-num.*
匹配。星形运算符返回可能最长的匹配。如果想要最短的匹配,请使用*?
试试这个:
p = re.compile("""^(ser-num.*?|\[ser-num.*?])(?: )?(\w+)?(?: )?(http://.*\.com/(?:s(?:erial)?|p(?:roduct)?)/\d+(?:/)?(?:\d+|(?:\w|-)+)?)""")
注意使用非贪婪星型:ser-num.*?
参考:
- 此处的
,*?
,+?
条目:??
推荐
属于第一组,因为它与部分regexpser-num.*
匹配。星形运算符返回可能最长的匹配。如果想要最短的匹配,请使用*?
试试这个:
p = re.compile("""^(ser-num.*?|\[ser-num.*?])(?: )?(\w+)?(?: )?(http://.*\.com/(?:s(?:erial)?|p(?:roduct)?)/\d+(?:/)?(?:\d+|(?:\w|-)+)?)""")
注意使用非贪婪星型:ser-num.*?
参考:
- 此处的
,*?
,+?
条目:??
(?:)?
来表示空格,而不是仅仅用`?`?或者甚至可能用\s*
来表示空格,用(\w*)
来表示可选单词?罪魁祸首是*
;使用\S*
进行贪婪的非空格字符匹配。为什么要使用(?:)?
进行空格匹配,而不仅仅是使用`?`?或者甚至可能使用\S*
进行空格匹配,(\w*)
进行可选单词匹配?罪魁祸首是*
;使用\S*
进行贪婪的非空格字符匹配。为什么要使用(?:)?
进行空格匹配,而不仅仅是使用`?`?或者甚至可能使用\S*
进行空格匹配,(\w*)
进行可选单词匹配?罪魁祸首是*
;使用\S*
进行贪婪的非空格字符匹配。为什么要使用(?:)?
进行空格匹配,而不仅仅是使用`?`?或者甚至可能使用\S*
进行空格匹配,(\w*)
进行可选单词匹配?罪魁祸首是*
;使用\S*
进行贪婪的非空格字符匹配。明显的“应用非贪婪匹配”提供了最简单的更改+1显而易见的“应用非贪婪匹配”提供了最简单的更改+1显而易见的“应用非贪婪匹配”提供了最简单的更改+1显而易见的“应用非贪婪匹配”提供了最简单的更改+1.