如何在Python的正则表达式中使用?和?:及:?
我明白了
* = "zero or more"
? = "zero or more" ...what's the difference?
另外,?: 这个符号在我的书里有提到,它说这是一个“细微之处”,但我不太清楚它到底是干什么的!
4 个回答
? 表示零个或一个
你可以用 (?:) 来进行分组,但它不会像 () 那样把分组的内容保存到一个临时变量里
?: << 我的书里提到这个,它说这是一个“细微之处”,但我不知道这些到底是干嘛的!
如果你的书真是这么说的,那我建议你换一本更好的书。
在括号里面(更准确地说,是在开括号后面),?
有另一种意思。它开始一个选项的组,这些选项只在括号的范围内有效。?:
是这些选项的一种特殊情况。要理解这个特殊情况,你首先得知道括号是用来创建捕获组的:
a(.)c
这是一个正则表达式,它可以匹配任何以a
开头、以c
结尾的三字母字符串。中间的字符是(或多或少)随意的。因为你把它放在了括号里,所以你可以捕获它:
m = re.search('a(.)c', 'abcdef')
print m.group(1)
这将打印出b
,因为m.group(1)
捕获了第一个括号里的内容(group(0)
捕获的是整个匹配的结果,这里是abc
)。
现在,考虑这个正则表达式:
a(?:.)c
这里没有进行捕获——这就是在开括号后面加?:
的意思。也就是说,下面的代码会失败:
print m.group(1)
因为没有组1!
正如Manu所说,?
的意思是“零次或一次”。这和{0,1}
是一样的。
而你提到的?:
,可能是指(?:X)
,这里的X是其他的字符串。这被称为“非捕获组”。
通常,当你用括号把某些东西包起来时,你是在把这些括号匹配到的内容分组。例如,正则表达式.(.).(.)
可以匹配任何四个字符(除了换行符),并把第二个字符存储在组1中,把第四个字符存储在组2中。但是,当你写.(?:.).(.)
时,只有第四个字符会被存储在组1中,括号(?:.)
之间的内容会被匹配,但不会被“记住”。
这里有个小演示:
import re
m = re.search('.(.).(.)', '1234')
print m.group(1)
print m.group(2)
# output:
# 2
# 4
m = re.search('.(?:.).(.)', '1234')
print m.group(1)
# output:
# 4
你可能会问:“为什么要使用这个非捕获组呢?”其实,有时候你想在两个字符串之间做一个“或”的匹配,比如你想匹配字符串“www.google.com”或“www.yahoo.com”,你可以写成www\.google\.com|www\.yahoo\.com
,但更简洁的写法是www\.(google|yahoo)\.com
。不过,如果你不打算对这个组捕获到的内容(比如“google”或“yahoo”)做什么有用的事情,那你就可以使用非捕获组:www\.(?:google|yahoo)\.com
。当正则引擎不需要“记住”子串“google”或“yahoo”时,你的应用程序或脚本运行会更快。当然,对于相对较小的字符串,这种差别不大,但当你的正则表达式和字符串变得更大时,可能就会有明显的差别。
想要更好地理解非捕获组的例子,可以看看Chris Lutz在下面的评论。