Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中的正则表达式,这可以改进吗?_Python_Regex - Fatal编程技术网

python中的正则表达式,这可以改进吗?

python中的正则表达式,这可以改进吗?,python,regex,Python,Regex,我有一段代码可以查找以@或#开头的单词 现在让我恼火的是重复\w+。我相信有一种方法可以做到这一点 p = re.findall(r'(@|#)\w+', str) 这将产生相同的结果,但不会,而是只返回和@。如何更改该正则表达式,使我不会重复\w+?这个密码很接近 p = re.findall(r'((@|#)\w+)', str) 但是它返回[('@many','@'),('@this','@'),('#tweet','#')](注意额外的'@','@',和'#') 另外,如果我重复这个

我有一段代码可以查找以@或#开头的单词

现在让我恼火的是重复\w+。我相信有一种方法可以做到这一点

p = re.findall(r'(@|#)\w+', str)
这将产生相同的结果,但不会,而是只返回
@
。如何更改该正则表达式,使我不会重复
\w+
?这个密码很接近

p = re.findall(r'((@|#)\w+)', str)
但是它返回
[('@many','@'),('@this','@'),('#tweet','#')]
(注意额外的'@','@',和'#')

另外,如果我重复这个
re.findall
code 500000次,这能被编译成一个模式然后更快吗?

解决方案 您有两个选择:

  • 使用非捕获组:
    (?:@|#)\w+
  • 或者更好的是,一个字符类:
    [@#]\w+
工具书类

理解
findall
您遇到的问题是由于
findall
返回匹配的方式取决于存在多少捕获组

让我们仔细看看这个模式(注释以显示组):

捕获组允许我们在整个模式的子模式中保存匹配项

p = re.compile(r'((@|#)\w+)')
m = p.match('@tweet')
print m.group(1)
# @tweet
print m.group(2)
# @

现在让我们看一下Python文档的代码< Re>代码>模块:

:返回字符串中模式的所有非重叠匹配项,作为字符串列表。从左到右扫描字符串,并按找到的顺序返回匹配项。如果模式中存在一个或多个组,则返回组列表;如果模式有多个组,则这将是元组列表

这就解释了为什么会出现以下情况:

str = 'lala @tweet boo #this &that @foo#bar'

print(re.findall(r'((@|#)\w+)', str))
# [('@tweet', '@'), ('#this', '#'), ('@foo', '@'), ('#bar', '#')]
print(re.findall(r'(@|#)\w+', str))
# ['@', '#', '@', '#']
如前所述,由于模式有多个组,
findall
返回一个元组列表,每个匹配对应一个元组。每个元组为给定匹配提供组捕获的内容

文档还解释了为什么您会得到以下结果:

str = 'lala @tweet boo #this &that @foo#bar'

print(re.findall(r'((@|#)\w+)', str))
# [('@tweet', '@'), ('#this', '#'), ('@foo', '@'), ('#bar', '#')]
print(re.findall(r'(@|#)\w+', str))
# ['@', '#', '@', '#']
现在模式只有一个组,并且
findall
返回该组的匹配列表

相比之下,上面给出的解决方案模式没有任何捕获组,这就是它们根据您的期望工作的原因:

print(re.findall(r'(?:@|#)\w+', str))
# ['@tweet', '#this', '@foo', '#bar']

print(re.findall(r'[@#]\w+', str))
# ['@tweet', '#this', '@foo', '#bar']
工具书类
    • |
附件

谢谢!这是可以编译然后在模式中重用的东西吗?@tipu-“任何东西”都可以编译/重用,别忘了接受answer@tipu:我已经用更多特定于Python的信息更新了答案。