Python 如何在正则表达式中为一组条件定义量词?

Python 如何在正则表达式中为一组条件定义量词?,python,regex,Python,Regex,我有这个字符串: "Za @Foo_Bar: @BAR_foo @FooBAR @BArfoo" 还有这样的正则表达式模式: ((Za\s)?@[A-Za-z0-9_]*)|(@[A-Za-z0-9_]*) 或 我希望它返回以下列表: ['Za @Foo_Bar','BAR_foo','FooBAR','BArfoo'] 但我得到了意想不到的结果: >>> import re >>> import regex >>> a = "Za

我有这个字符串:

"Za @Foo_Bar: @BAR_foo @FooBAR @BArfoo"
还有这样的正则表达式模式:

((Za\s)?@[A-Za-z0-9_]*)|(@[A-Za-z0-9_]*)

我希望它返回以下列表:

['Za @Foo_Bar','BAR_foo','FooBAR','BArfoo'] 
但我得到了意想不到的结果:

>>> import re
>>> import regex
>>> a = "Za @Foo_Bar: @BAR_foo @FooBAR @BArfoo"
>>> regex.fullmatch(u'((Za\s)?@[A-Za-z0-9_]*)|(@[A-Za-z0-9_]*)',a) is None
True
>>> re.findall(u'((Za\s)?@[A-Za-z0-9_]*)|(@[A-Za-z0-9_]*)',a)
[('Za @Foo_Bar', 'Za ', ''), ('@BAR_foo', '', ''), ('@FooBAR', '', ''), ('@BArfoo', '', '')]
第二个结果更具说服力,但它包含许多垃圾值:

>>> regex.findall(u'((Za\s)?@[A-Za-z0-9_]*)|(@[A-Za-z0-9_]*)',a)
[('Za @Foo_Bar', 'Za ', ''), ('@BAR_foo', '', ''), ('@FooBAR', '', ''), ('@BArfoo', '', '')]
>>> match  = re.search(u'((Za\s)?@[A-Za-z0-9_]*)|(@[A-Za-z0-9_]*)',a)
>>> match.groups()
('Za @Foo_Bar', 'Za ', None)

为什么
fullmatch
返回
None
?如何获得一个干净的列表?

作为替代方法,您可以使用
(?并在可选冒号上拆分,后跟空格和
@
,字符串中的第一个除外:

import re
s = "Za @Foo_Bar: @BAR_foo @FooBAR @BArfoo"
print(re.split('(?<!\AZa):? @', s))

|

作为替代,您可以使用
(?并在可选冒号上拆分,后跟空格和
@
,字符串中的第一个除外:

import re
s = "Za @Foo_Bar: @BAR_foo @FooBAR @BArfoo"
print(re.split('(?<!\AZa):? @', s))
|

regex.fullmatch()
是这里使用的错误方法,我认为您不理解它的用途

从:

fullmatch
的行为类似于
match
,只是它必须匹配所有字符串

您的模式不匹配所有输入字符串。只有当模式覆盖了从第一个字符到最后一个字符的所有内容时,
fullmatch()
才会返回匹配

其中,
re.match()
仅在字符串开头匹配,就像您将
\A
添加到模式的开头一样,
regex.fullmatch()
匹配,就像您将
\A
添加到模式的开头,并且将
\Z
添加到模式的结尾一样

请注意,您不需要
|(@[A-Za-z0-9\]*)
选项;当
(Za\s)?@[A-Za-z0-9\]*
部分与
(Za\s)?
不匹配时,该模式已完全覆盖

要获得一个干净的列表,请使用
re.findall()
,但要使用
(?:…)
非捕获组来覆盖可选部分,这样就不会在
re.findall()
结果中获得单独的字符串:

>>> import re
>>> a = "Za @Foo_Bar: @BAR_foo @FooBAR @BArfoo"
>>> re.findall(r'(?:Za\s)?@[A-Za-z0-9_]*', a)
['Za @Foo_Bar', '@BAR_foo', '@FooBAR', '@BArfoo']
在没有捕获组的情况下,将返回整个匹配。

regex.fullmatch()
在这里使用的方法是错误的,我认为您不了解它的用途

从:

fullmatch
的行为类似于
match
,只是它必须匹配所有字符串

您的模式不匹配所有输入字符串。只有当模式覆盖了从第一个字符到最后一个字符的所有内容时,
fullmatch()
才会返回匹配

其中,
re.match()
仅在字符串开头匹配,就像您将
\A
添加到模式的开头一样,
regex.fullmatch()
匹配,就像您将
\A
添加到模式的开头,并且将
\Z
添加到模式的结尾一样

请注意,您不需要
|(@[A-Za-z0-9\]*)
选项;当
(Za\s)?@[A-Za-z0-9\]*
部分与
(Za\s)?
不匹配时,该模式已完全覆盖

要获得一个干净的列表,请使用
re.findall()
,但要使用
(?:…)
非捕获组来覆盖可选部分,这样就不会在
re.findall()
结果中获得单独的字符串:

>>> import re
>>> a = "Za @Foo_Bar: @BAR_foo @FooBAR @BArfoo"
>>> re.findall(r'(?:Za\s)?@[A-Za-z0-9_]*', a)
['Za @Foo_Bar', '@BAR_foo', '@FooBAR', '@BArfoo']
如果没有捕获组,则返回整个匹配。

不使用组:

import re

s = "Za @Foo_Bar: @BAR_foo @FooBAR @BArfoo"
g = re.findall(r'(?:Za\s)@\w+|(?<=@)\w+', s)
print(g)
说明:

['Za @Foo_Bar', 'BAR_foo', 'FooBAR', 'BArfoo']
  (?:Za\s)  # non capture group
  @         # @
  \w+       # 1 or more word character
|           #
  (?<=@)    # lookbehind, make sure we have @ before
  \w+       # 1 or more word character
(?:Za\s)#非捕获组
@         # @
\w+#1个或多个单词字符
|           #
(?不要使用组:

import re

s = "Za @Foo_Bar: @BAR_foo @FooBAR @BArfoo"
g = re.findall(r'(?:Za\s)@\w+|(?<=@)\w+', s)
print(g)
说明:

['Za @Foo_Bar', 'BAR_foo', 'FooBAR', 'BArfoo']
  (?:Za\s)  # non capture group
  @         # @
  \w+       # 1 or more word character
|           #
  (?<=@)    # lookbehind, make sure we have @ before
  \w+       # 1 or more word character
(?:Za\s)#非捕获组
@         # @
\w+#1个或多个单词字符
|           #
(?