正则表达式
    正则表达式有强大并且标准化的方法来处理字符串查找、替换以及用复杂模式来解析文本。
    正则表达式的语法比程序代码更紧凑,格式更严格,比用组合调用字符串处理函数的方法更具有可读性。
    还可以在正则表达式中嵌入注释信息,这样就可以使它有自文档化的功能。


匹配符:
    ^       匹配字符串开始位置。在多行字符串模式匹配每一行的开头。
    $       匹配字符串结束位置。在多行字符串模式匹配每一行的结尾。
    .       匹配除了换行符外的任何字符,在 alternate 模式(re.DOTALL)下它甚至可以匹配换行。
    \A      匹配字符串开头
    \Z      匹配字符串结尾
    \b      匹配一个单词边界。即 \w 与 \W 之间。
    \B      匹配一个非单词边界;相当于类 [^\b]。
    \d      匹配一个数字。
    \D      匹配一个任意的非数字字符。
    \s      匹配任何空白字符;它相当于类  [ \t\n\r\f\v]。
    \S      匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。
    \w      匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
    \W      匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]。
    x?      匹配可选的x字符。即是0个或者1个x字符。
    x*      匹配0个或更多的x。
    x+      匹配1个或者更多x。
    x{n,m}  匹配n到m个x,至少n个,不能超过m个。
    (a|b|c) 匹配单独的任意一个a或者b或者c。
    (x)     捕获组,小括号括起来即可,它会记忆它匹配到的字符串。
            可以用 re.search() 返回的匹配对象的 groups()函数来获取到匹配的值。
    \1      记忆组,它表示记住的第一个分组;如果有超过一个的记忆分组,可以使用 \2 和 \3 等等。
            记忆组的内容也要小括号括起来。
    (?iLmsux)          iLmsux的每个字符代表一种匹配模式
        re.I(re.IGNORECASE): 忽略大小写
        re.M(re.MULTILINE): 多行模式
        re.S(re.DOTALL):  单行
        re.L(re.LOCALE): 使预定字符类 \w \W \b \B \s \S 匹配本地字符,对中文支持不好
        re.U(re.UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
        re.X(re.VERBOSE): 忽略多余的空白字符,并可以加入注释。
    (?:表达式)         无捕获组。与捕获组表现一样,只是没有内容。
    (?P<name>表达式)   命名组。与记忆组一样,只是多了个名称。
    (?P=name)          命名组的逆向引用。
    (?#...)            “#”后面的将会作为注释而忽略掉。例如:“ab(?#comment)cd”匹配“abcd”
    (?=...)            之后的字符串需要匹配表达式才能成功匹配。不消耗字符串内容。 例:“a(?=\d)”匹配“a12”中的“a”
    (?!...)            之后的字符串需要不匹配表达式才能成功匹配。不消耗字符串内容。 例:“a(?!\d)”匹配“abc”中的“a”
    (?<=...)           之前的字符串需要匹配表达式才能成功匹配。不消耗字符串内容。 例:“(?<=\d)a”匹配“2a”中的“a”
    (?<!...)           之前的字符串需要不匹配表达式才能成功匹配。不消耗字符串内容。 例:“(?<!\d)a”匹配“sa”中的“a”
                       注:上面4个表达式的里面匹配的内容只能是一个字符,多个则报错。
    (?(id/name)yes-pattern|no-pattern)  如果编号为 id 或者别名为 name 的组匹配到字符串,则需要匹配yes-pattern,
    否则需要匹配no-pattern。 “|no-pattern”可以省略。如:“(\d)ab(?(1)\d|c)”匹配到“1ab2”和“abc”

匹配两边关键词 取中间的值
str2 = '<[email protected]>'
print re.findall(r"(?<=<12).+([email protected]>)", str2)
结果: ['345']

元字符:
    "[" 和 "]"
        它们常用来匹配一个字符集。字符可以单个列出,也可以用“-”号分隔的两个给定字符来表示一个字符区间。
            例如,[abc] 将匹配"a", "b", 或 "c"中的任意一个字符;也可以用区间[a-c]来表示同一字符集,和前者效果一致。
        元字符在类别里并不起作用。例如,[a$]将匹配字符"a" 或 "$" 中的任意一个;"$" 在这里恢复成普通字符。
        也可以用补集来匹配不在区间范围内的字符。其做法是把"^"作为类别的首个字符;其它地方的"^"只会简单匹配 "^"字符本身。
            例如,[^5] 将匹配除 "5" 之外的任意字符。
        特殊字符都可以包含在一个字符类中。如,[\s,.]字符类将匹配任何空白字符或","或"."。
    反斜杠 "\"。
        做为 Python 中的字符串字母,反斜杠后面可以加不同的字符以表示不同特殊意义。
        它也可以用于取消所有的元字符,这样你就可以在模式中匹配它们了。
            例如,需要匹配字符 "[" 或 "\",可以在它们之前用反斜杠来取消它们的特殊意义: \[ 或 \\。

建议使用原始字符串:
    建议在处理正则表达式的时候总是使用原始字符串。如: r'\bROAD$', 而不要写成 '\\bROAD$'
    否则,会因为理解正则表达式而消耗大量时间(正则表达式本身就已经够让人困惑的了)。

无捕获组:
    有时你想用一个组去收集正则表达式的一部分,但又对组的内容不感兴趣。你可以用一个无捕获组“(?:...)”来实现这项功能。
    除了捕获匹配组的内容之外,无捕获组与捕获组表现完全一样;可以在其中放置任何字符、匹配符,可以在其他组(无捕获组与捕获组)中嵌套它。
    无捕获组对于修改已有组尤其有用,因为可以不用改变所有其他组号的情况下添加一个新组。
    捕获组和无捕获组在搜索效率方面也一样。

命名组:
    与用数字指定组不同的是,它可以用名字来指定。除了该组有个名字之外,命名组也同捕获组是相同的。
    (?P<name>...) 定义一个命名组,(?P=name) 则是对命名组的逆向引用。
    MatchObject 的方法处理捕获组时接受的要么是表示组号的整数,要么是包含组名的字符串。所以命名组可以通过数字或者名称两
    种方式来得到一个组的信息。

松散正则表达式:
    为了方便阅读和维护,可以使用松散正则表达式,它与普通紧凑的正则表达式有两点不同:
    1, 空白符被忽略。空格、制表符(tab)和回车会被忽略。如果需要匹配他们,可以在前面加一个“\”来转义。
    2, 注释被忽略。注释以“#”开头直到行尾,与python代码中的一样。
    使用松散正则表达式,需要传递一个叫 re.VERBOSE的 参数。详细见下面例子。

re 有几个重要的函数:

match(): 匹配字符串开始位置。
search(): 扫描字符串,找到第一个位置。
findall(): 找到全部匹配,以列表返回。
finditer(): 找到全部匹配,以迭代器返回。
match 和 search 仅匹配一次,匹配不到返回 None。

>>> import re

>>> s = "12abc345ab"

>>> m = re.match(r"\d+", s)
>>> m.group(), m.span()
('12', (0, 2))

>>> m = re.match(r"\d{3,}", s)
>>> m is None
True

>>> m = re.search(r"\d{3,}", s)
>>> m.group(), m.span()
('345', (5, 8))

>>> m = re.search(r"\d+", s)
>>> m.group(), m.span()
('12', (0, 2))
findall 返回列表 (或空列表),finditer 和 match、search 一样返回 MatchObject 对象。

>>> ms = re.findall(r"\d+", s)
>>> ms
['12', '345']

>>> ms = re.findall(r"\d{5}", s)
>>> ms
[]

>>> for m in re.finditer(r"\d+", s): print m.group(), m.span()
...
12 (0, 2)
345 (5, 8)

>>> for m in re.finditer(r"\d{5}", s): print m.group(), m.span() # 返回空列表
...
>>>
MatchObject

match、search、finditer 返回的对象 —— MatchObject。

group(): 返回匹配的完整字符串。
start(): 匹配的开始位置。
end(): 匹配的结束位置。
span(): 包含起始、结束位置的元组。
groups(): 返回分组信息。
groupdict(): 返回命名分组信息。
>>> m = re.match(r"(\d+)(P<letter>[abc]+)", s)

>>> m.group()
'12abc'

>>> m.start()
0

>>> m.end()
5

>>> m.span()
(0, 5)

>>> m.groups()
('12', 'abc')

>>> m.groupdict()
{'letter': 'abc'}
group() 可以接收多个参数,用于返回指定序号的分组。

>>> m.group(0)
'12abc'

>>> m.group(1)
'12'

>>> m.group(2)
'abc'

>>> m.group(1,2)
('12', 'abc')

>>> m.group(0,1,2)
('12abc', '12', 'abc')
start()、end() 和 span() 同样能接收分组序号。和 group() 一样,序号 0 表示整体匹配结果。

>>> m.start(0), m.end(0)
(0, 5)

>>> m.start(1), m.end(1)
(0, 2)

>>> m.start(2), m.end(2)
(2, 5)

>>> m.span(0)
(0, 5)

>>> m.span(1)
(0, 2)

>>> m.span(2)
(2, 5)
编译标志

可以用 re.I、re.M 等参数,也可以直接在表达式中添加 "(iLmsux)" 标志。

s: 单行。"." 匹配包括换行符在内的所有字符。
i: 忽略大小写。
L: 让 "\w" 能匹配当地字符,貌似对中文支持不好。
m: 多行。
x: 忽略多余的空白字符,让表达式更易阅读。
u: Unicode。
试试看。

>>> re.findall(r"[a-z]+", "%123Abc%45xyz&")
['bc', 'xyz']

>>> re.findall(r"[a-z]+", "%123Abc%45xyz&", re.I)
['Abc', 'xyz']

>>> re.findall(r"(i)[a-z]+", "%123Abc%45xyz&")
['Abc', 'xyz']
下面这么写好看多了吧?

>>> pattern = r"""
...     (\d+) # number
...     ([a-z]+) # letter
... """

>>> re.findall(pattern, "%123Abc\n%45xyz&", re.I | re.S | re.X)
[('123', 'Abc'), ('45', 'xyz')]
组操作

命名组:(P...)

>>> for m in re.finditer(r"(P<number>\d+)(P<letter>[a-z]+)", "%123Abc%45xyz&", re.I):
...     print m.groupdict()
...
{'number': '123', 'letter': 'Abc'}
{'number': '45', 'letter': 'xyz'}
无捕获组:(:...),作为匹配条件,但不返回。

>>> for m in re.finditer(r"(:\d+)([a-z]+)", "%123Abc%45xyz&", re.I):
...     print m.groups()
...
('Abc',)
('xyz',)
反向引用:\ 或 (P=name),引用前面的组。

>>> for m in re.finditer(r"<a>\w+</a>", "%<a>123Abc</a>%<b>45xyz</b>&"):
...     print m.group()
...
<a>123Abc</a>

>>> for m in re.finditer(r"<(\w)>\w+</(\1)>", "%<a>123Abc</a>%<b>45xyz</b>&"):
...     print m.group()
...
<a>123Abc</a>
<b>45xyz</b>

>>> for m in re.finditer(r"<(P<tag>\w)>\w+</(P=tag)>", "%<a>123Abc</a>%<b>45xyz</
b>&"):
...     print m.group()
...
<a>123Abc</a>
<b>45xyz</b>
正声明 (=...):组内容必须出现在右侧,不返回。 负声明 (...):组内容不能出现在右侧,不返回。 反向正声明 (<=):
组内容必须出现在左侧,不返回。 反向负声明 (<):组内容不能出现在左侧,不返回。

>>> for m in re.finditer(r"\d+(=[ab])", "%123Abc%45xyz%780b&", re.I):
...     print m.group()
...
123
780

>>> for m in re.finditer(r"(<\d)[a-z]{3,}", "%123Abc%45xyz%byse&", re.I):
... print m.group()
...
byse
更多信息请阅读官方文档或更专业的书籍。

修改

split: 用 pattern 做分隔符切割字符串。如果用 "(pattern)",那么分隔符也会返回。

>>> re.split(r"\W", "abc,123,x")
['abc', '123', 'x']

>>> re.split(r"(\W)", "abc,123,x")
['abc', ',', '123', ',', 'x']
sub: 替换子串。可指定替换次数。

>>> re.sub(r"[a-z]+", "*", "abc,123,x")
'*,123,*'

>>> re.sub(r"[a-z]+", "*", "abc,123,x", 1)
'*,123,x'
subn() 和 sub() 差不多,不过返回 "(新字符串,替换次数)"。

>>> re.subn(r"[a-z]+", "*", "abc,123,x")
('*,123,*', 2)
还可以将替换字符串改成函数,以便替换成不同的结果。

>>> def repl(m):
...     print m.group()
...     return "*" * len(m.group())
...

>>> re.subn(r"[a-z]+", repl, "abc,123,x")
abc
x
('***,123,*', 2)
StringIO
提供类文件接口的字符串缓冲区,可选用性能更好的 cStringIO 版本。

>>> from contextlib import closing
>>> from cStringIO import StringIO

>>> with closing(StringIO("ab")) as f:
...     print >> f, "cd"
...     f.write("1234")
...     print f.getvalue()
abcd
1234
建议用 with 上下文确保调用 close() 方法释放所占用内存。用 getvalue() 返回字符串前,必须确保是打开状态 (closed = False)。

struct
struct 看上去有点像 format,区别是它输出的是二进制字节序列。可以通过格式化参数,指定类型、长度、字节序(大小端)、内存对齐等。

>>> from struct import *

>>> hexstr = lambda s: map(lambda c: hex(ord(c)), s)

>>> s = pack("i", 0x1234)

>>> hexstr(s)      # 4 字节整数小端排列
['0x34', '0x12', '0x0', '0x0']

>>> unpack("i", s)      # 还原。4660 = 0x1234
(4660,)

>>> s = pack(">i", 0x1234)    # 大端

>>> hexstr(s)
['0x0', '0x0', '0x12', '0x34']

>>> s = pack("2i2s", 0x12, 0x34, "ab")   # 多值。注意指定字符串长度。

>>> hexstr(s)
['0x12', '0x0', '0x0', '0x0', '0x34', '0x0', '0x0', '0x0', '0x61', '0x62']

>>> unpack("2i2s", s)
(18, 52, 'ab')
还可以将结果输出到 bytearray、array、ctypes.create_str_buffer() 等缓冲对象中。

>>> fmt = "3bi2s"
>>> size = calcsize(fmt)   # 计算指定格式转换所需的字节长度。

>>> buffer = bytearray(size)

>>> pack_into(fmt, buffer, 0, 0x1, 0x2, 0x3, 0x1FFFFF, "ab")

>>> buffer
bytearray(b'\x01\x02\x03\x00\xff\xff\x1f\x00ab')

>>> unpack_from(fmt, str(buffer), 0)
(1, 2, 3, 2097151, 'ab')

results matching ""

    No results matching ""