Awk

expr ~ /r/
/r/ { action }                          # $0 ~ /r/ { action }

特殊字符包括:^ $ . [ ] | ( ) * + ?

c
普通字符
\c
转义字符
.
任意字符,包括换行符
^
字符串开头
$
字符串结尾
[c1c2c3…]
匹配括号内任意字符
[^c1c2c3…]
匹配除括号内任意字符
r1r2
连续匹配
r1 | r2
选择匹配
r*
重复匹配0次或多次
r+
重复匹配多次
r?
匹配0次或一次
(r)
分组
^[_a-zA-Z][_a-zA-Z0-9]*$
匹配AWK标识符
^[-+]?([0-9]+\.?|\.[0-9])[0-9]*([eE][-+]?[0-9]+)?$
匹配数字

Grep

[...]           匹配列表中任意一个字符
[^...]          匹配列表外任意一个字符

[:alnum:], [:alpha:], [:cntrl:], [:digit:], [:graph:], [:lower:], [:print:],
[:punct:], [:space:], [:upper:], [:xdigit:]
[[:alnum:]]     等价于[0-9A-Za-z]

.               任意字符
^ $             行首 行尾
\< \>           词首 词尾
\b \B           词边界 非词边界
\w \W           [_[:alnum:]] [^_[:alnum:]]


?               最多一次
*               任意次
+               最少一次
{n}             n次
{n,}            至少n次
{,m}            至多m次
{n,m}           n次到m次之间
|               选择任意一组匹配

如果使用基本正则表达式,? + {} () |将失去特殊含义,需要加上转义。所以当表达式含有这些元字符时,最好启用扩展正则表达式选项。

Python re module

正则表达式被编译成字节码,然后用C编写的匹配引擎执行。元字符有其特殊含义,完整列表包括:. ^ $ * + ? { [ ] \ | ( )。中括号[]用来指定一个字符所属的字符集,如[abc][a-c]含义相同,比较重要的一点是元字符在字符集中会退化为普通字符,有两个例外,一个是放在首部的^字符,表示补集,另一个是转义字符。提到转义字符,它除了退化元字符的功能外,还能够转义普通字符以表示特殊字符集。

转义序列 等价表达式 含义
\d [0-9] 数字
\D [^0-9] 非数字
\s [ \t\n\r\f\v] 空白字符
§ [^ \t\n\r\f\v] 非空白字符
\w [a-zA-Z0-9_] 字母数字
\W [^a-zA-Z0-9_] 非字母数字
\A   只匹配字符串首
\Z   只匹配字符串尾
\b   零宽界定符:单词边界
\B   零宽界定符:非单词边界

点号.用于匹配任何字符。

星号*用于指定重复任意次,包括0次,等价于{0,},加号+和星号的唯一区别是不允许0次,等价于{1,}。问号?允许0次或1次,等价于{0,1}。区间表示法{m, n}表示至少m次,最多n次,如果忽略下界则下界为0,如果忽略上界则上界为无穷大。

反斜杠非常麻烦,比方要匹配的字符就是\section,编译正则表达式要保留反斜杠就必须转义,因此要传递\\section给编译器。为了传递\\section编译器,Python字符串就得保留两个反斜杠,因此要在Python字符串中写\\\\section,是不是很麻烦?不过好在Python提供了raw字符串,它不会对反斜杠转义,故r"\\section"就能够表示两个反斜杠。

小括号用来分组,分组不好理解,举个例子:

import re
p = re.compile('(a(b)c)d')
m = p.match('abcd')
m.group(0)                              # 'abcd'
m.group(1)                              # 'abc'
m.group(2)                              # 'b'
m.group(2,1,2)                          # ('b', 'abc', 'b')
m.groups()                              # ('abc', 'b') except 0
|
相当于or
^
匹配行首
$
匹配行尾

模式需要编译,因为它是一个C扩展模块,编译好一个正则表达式对象之后就可以用来工作了,以下是编译后pattern的成员函数:

match
判定是否匹配,若匹配返回匹配对象,仅从字符串开始处匹配
search
搜索匹配位置,若找到返回匹配对象
findall
找出所有匹配,返回位置列表
finditer
找出所有匹配,返回位置迭代器
split(str, [maxn])
在匹配处分片
sub(str, sstr, [count=0])
替换匹配子串,返回新字符串
subn()
sub(),返回新的字符串和次数

上面的成员函数返回一个匹配对象,匹配对象支持的方法如下:

group()
被匹配的字符串
start()
匹配开始位置
end()
匹配结束位置
span()
匹配位置元组,即(start, end)

编译标志:

IGNORECASE
忽略大小写
LOCALE
影响\w \W \b \B
MULTILINE
退化^ $
DOTALL
.能够匹配换行
VERBOSE
允许注释,使得代码可读性好

另外也可以直接调用全局函数match()search()split()等函数,这样可以省略编译步骤,让Python来帮我们做。

charref = re.compile(r"""&[[]]  # Start of a numeric entity reference
(
[0-9]+[^0-9] |                  # Decimal form
0[0-7]+[^0-7] |                 # Octal form
x[0-9a-fA-F]+[^0-9a-fA-F]       # Hexadecimal form
)
""", re.VERBOSE)
import re
p = re.compile(r'\W+')
p2 = re.compile(r'(\W+)')
print p.split('This... is a test.')
print p2.split('This... is a test.')
['This', 'is', 'a', 'test', '']
['This', '... ', 'is', ' ', 'a', ' ', 'test', '.', '']