python re(八)

更多的元字符

还有一些我们还没展示的元字符,其中的大部分将在本节展示。


剩下来要讨论的一部分元字符是零宽界定符(zero-width assertions)。它们并不会使引擎在处理字符串时更快;相反,它们根本就没有对应任何字符,只是简单的成功或失败。举个例子, "b 是一个在单词边界定位当前位置的界定符(assertions),这个位置根本就不会被 "b 改变。这意味着零宽界定符(zero-width assertions)将永远不会被重复,因为如果它们在给定位置匹配一次,那么它们很明显可以被匹配无数次。

|


可选项,或者 "or" 操作符。如果 A 和 B 是正则表达式,A|B 将匹配任何匹配了 "A" 或 "B" 的字符串。| 的优先级非常低,是为了当你有多字符串要选择时能适当地运行。Crow|Servo 将匹配"Crow" 或 "Servo", 而不是 "Cro", 一个 "w" 或 一个 "S", 和 "ervo"。


为了匹配字母 "|",可以用 "|,或将其包含在字符类中,如[|]。

^


匹配行首。除非设置 MULTILINE 标志,它只是匹配字符串的开始。在 MULTILINE 模式里,它也可以直接匹配字符串中的每个换行。


例如,如果你只希望匹配在行首单词 "From",那幺 RE 将用 ^From。

# !python

>>>   print  re.search( ' ^From ' ' From Here to Eternity ' )

< re.MatchObject instance at 80c1520 >

>>>   print  re.search( ' ^From ' ' Reciting From Memory ' )

None

$


匹配行尾,行尾被定义为要么是字符串尾,要么是一个换行字符後面的任何位置。

# !python

>>>   print  re.search( ' }$ ' ' {block} ' )

< re.MatchObject instance at 80adfa8 >

>>>   print  re.search( ' }$ ' ' {block}  ' )

None

>>>   print  re.search( ' }$ ' ' {block}"n ' )

< re.MatchObject instance at 80adfa8 >

匹配一个 "$",使用 "$ 或将其包含在字符类中,如[$]。

"A


只匹配字符串首。当不在 MULTILINE 模式,"A 和 ^ 实际上是一样的。然而,在 MULTILINE 模式里它们是不同的;"A 只是匹配字符串首,而 ^ 还可以匹配在换行符之後字符串的任何位置。

"Z

Matches only at the end of the string. 
只匹配字符串尾。

"b

单词边界。这是个零宽界定符(zero-width assertions)只用以匹配单词的词首和词尾。单词被定义为一个字母数字序列,因此词尾就是用空白符或非字母数字符来标示的。


下面的例子只匹配 "class" 整个单词;而当它被包含在其他单词中时不匹配。

# !python

>>>  p  =  re.compile(r ' "bclass"b ' )

>>>   print  p.search( ' no class at all ' )

< re.MatchObject instance at 80c8f28 >

>>>   print  p.search( ' the declassified algorithm ' )

None

>>>   print  p.search( ' one subclass is ' )

None

当用这个特殊序列时你应该记住这里有两个微妙之处。第一个是 Python 字符串和正则表达式之间最糟的冲突。在 Python 字符串里,""b" 是反斜杠字符,ASCII值是8。如果你没有使用 raw 字符串时,那幺 Python 将会把 ""b" 转换成一个回退符,你的 RE 将无法象你希望的那样匹配它了。下面的例子看起来和我们前面的 RE 一样,但在 RE 字符串前少了一个 "r" 。

# !python

>>>  p  =  re.compile( ' "bclass"b ' )

>>>   print  p.search( ' no class at all ' )

None

>>>   print  p.search( ' "b '   +   ' class '   +   ' "b ' )

< re.MatchObject instance at 80c3ee0 >

第二个在字符类中,这个限定符(assertion)不起作用,"b 表示回退符,以便与 Python 字符串兼容。

"B


另一个零宽界定符(zero-width assertions),它正好同 "b 相反,只在当前位置不在单词边界时匹配。

分组

你经常需要得到比 RE 是否匹配还要多的信息。正则表达式常常用来分析字符串,编写一个 RE 匹配感兴趣的部分并将其分成几个小组。举个例子,一个 RFC-822 的头部用 ":" 隔成一个头部名和一个值,这就可以通过编写一个正则表达式匹配整个头部,用一组匹配头部名,另一组匹配头部值的方式来处理。


组是通过 "(" 和 ")" 元字符来标识的。 "(" 和 ")" 有很多在数学表达式中相同的意思;它们一起把在它们里面的表达式组成一组。举个例子,你可以用重复限制符,象 *, +, ?, 和 {m,n},来重复组里的内容,比如说(ab)* 将匹配零或更多个重复的 "ab"。

# !python

>>>  p  =  re.compile( ' (ab)* ' )

>>>   print  p.match( ' ababababab ' ).span()

(0, 
10 )

组用 "(" 和 ")" 来指定,并且得到它们匹配文本的开始和结尾索引;这就可以通过一个参数用 group()、start()、end() 和 span() 来进行检索。组是从 0 开始计数的。组 0 总是存在;它就是整个 RE,所以 `MatchObject` 的方法都把组 0 作为它们缺省的参数。稍後我们将看到怎样表达不能得到它们所匹配文本的 span。

# !python

>>>  p  =  re.compile( ' (a)b ' )

>>>  m  =  p.match( ' ab ' )

>>>  m.group()

' ab '

>>>  m.group(0)

' ab '

小组是从左向右计数的,从1开始。组可以被嵌套。计数的数值可以能过从左到右计算打开的括号数来确定。

# !python

>>>  p  =  re.compile( ' (a(b)c)d ' )

>>>  m  =  p.match( ' abcd ' )

>>>  m.group(0)

' abcd '

>>>  m.group( 1 )

' abc '

>>>  m.group( 2 )

' b '

group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。


# !python

>>>  m.group( 2 , 1 , 2 )

(
' b ' ' abc ' ' b ' )

The groups() 方法返回一个包含所有小组字符串的元组,从 
1  到 所含的小组号。

# !python

>>>  m.groups()

(
' abc ' ' b ' )

模式中的逆向引用允许你指定先前捕获组的内容,该组也必须在字符串当前位置被找到。举个例子,如果组 1 的内容能够在当前位置找到的话,"1 就成功否则失败。记住 Python 字符串也是用反斜杠加数据来允许字符串中包含任意字符的,所以当在 RE 中使用逆向引用时确保使用 raw 字符串。


例如,下面的 RE 在一个字符串中找到成双的词。

# !python

>>>  p  =  re.compile(r ' ("b"w+)"s+"1 ' )

>>>  p.search( ' Paris in the the spring ' ).group()

' the the '

象这样只是搜索一个字符串的逆向引用并不常见 -- 用这种方式重复数据的文本格式并不多见 -- 但你不久就可以发现它们用在字符串替换上非常有用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值