正则表达式中的经典书啊,真是强大啊
笔记嘛,都是做重点与细节.但发觉这本书到处都是细节,到处都是重点,真的好难去写啊!
就写个提纲吧!
默认所有例子规则适用于Perl .
一.正则表达式入门
正则由两种字符组成:特殊字符(元字符 matacharacter 和元字符序列 metasequences),文本普通字符 literal
一般把元字符和元字符序列统称为元字符.
元字符根据环境的不同表达不用的含义.
字符组
[] 匹配一个字符组内的字符
[^] 匹配一个未列出的字符(必须匹配).
字符组元字符: ^(开头) -(不为开头结尾) 如果不符合位置,也为普通字符.
字符组内支持转义字符和元字符序列.
转义
1.\ 加上元字符,匹配元字符的普通字符.
2.\ 加上非元字符,组成有特殊含义的元字符序列.
3.\ 加上除以上两种字符,默认匹配该字符,即忽视 \.
二.入门示例扩展
环视 lookaround
(?<=) 肯定逆序环视 子表达式能够匹配左侧文本
(?(?=) 肯定顺序环视 子表达式能够匹配右侧文本
(?!) 否定顺序环视 子表达式不能匹配右侧文本
环视不匹配字符,只匹配文本中的特定位置.
非捕获型括号
(?:) 只分组不捕获
三.正则表达式的特性和流派概览
正则表达式处理方式:集成式,程序式和面向对象式.
作为正则表达式的字符串
作为正则表达式的字符串经过特殊的字符串处理后,再传递给正则引擎识别.(详见第七章)
匹配模式
/i 不区分大小写模式
/x 宽松排列和注释模式
此模式忽略字符组[]外的所有空白字符.#符号和换行符之间的内容视为注释.
/s 点号通配模式 单行模式
.点号默认为不匹配换行符,该模式支持匹配换行符.
/m 增强行模式 多行模式
零长度断言
行/字符串起始位置 ^ \A
^ 普通模式 匹配字符串起始;
多行模式 匹配字符串起始或者任意的换行符之后的位置.
\A 两种模式 匹配字符串起始.
行/字符串结束位置 $ \Z \z
$ 普通模式 匹配字符串末尾或者末尾的换行符之前的位置.
多行模式 匹配字符串末尾或者任意的换行符之前的位置.
\Z 两种模式 匹配字符串末尾或者末尾的换行符之前的位置.
\z 两种模式 匹配字符串末尾.
注:在一个带换行符的字符串中,$ \Z 将匹配两处地方:一为换行符前,一为换行符后(字符串末尾).
匹配起始位置(或上一次匹配结束位置) \G
\G表示每次只在该位置匹配,不启动驱动过程,如果失败返回到起始位置,而不是从下一个位置继续匹配.该位置可用pos函数设定.
第一次迭代,\G同\Z,匹配字符串起始.
注释与模式修饰符
常见修饰字母 i x s m
模式修饰符 (?modifier) 例如 (?i) (?-i)
模式作用范围 (?modifier) 例如 (?!...)
注释 (?#...) #...
文字文本范围 \Q ... \E
分组,捕获,条件判断和控制
捕获/分组括号 () 和 \1 ,\2
仅用于分组括号 (?:)
固化分组 (?>)
匹配优先量词 * + ? {min,max}
忽略优先量词 *? +? ?? {min,max}?
占有优先量词 *+ ++ ?+ {min,max)+
条件判断 (?if then |else)
if是特殊的条件表达式.then和else表示普通的子表达式,作用于匹配.可省略后面的 |esle内容.
对捕获符号做测试 (?(1) then|else) 表示验证第一个捕获括号是否参与匹配.
对环视做测试 (?(?=...)then|else)
对内嵌代码做测试 (?(?{...})then|else)
四.表达式的匹配原理
正则引擎
NFA 非确定型有穷自动机
DFA 确定型有穷自动机
规则
1.优先选择最左端的匹配结果
2.标准量词是匹配优先
传统 NFA与DFA的比较
NFA
1.匹配过程类似于深度搜索,一条路走到死.然后回溯.
2.最左但不最长匹配,而是最左最先匹配.
3.支持捕获括号,反向引用,环视,非匹配优先量词,占有优先量词和固化分组.
DFA
1.匹配过程类似于广度搜索,步步为营.在匹配之前已经内建一张路线图,匹配时根据路线图进行.
2.最左最长匹配.
3.不支持NFA的第三条.
传统 NFA与POSIX NFA
传统 NFA 满足最左最先匹配原则,找到第一个匹配就停下来.
POSIX NFA 满足最左最长匹配原则,通过匹配所有分支,选择最长匹配结果.
正则引擎
DFA awk, egrep, flex, flex, lex, mysql, procmail
传统 NFA GNU Emacs, Java, grep, less, more .NET语言, PCRE library, Perl, PHP, Python, Ruby, sed, vi
POSIX NFA mawk, GNU Emacs(明确指定时使用)
DFA/NFA混合 GNU awk, GNU grep/egrep, Tcl
五.正则表达式实用技巧
六.打造高效的正则表达式
七.Perl正则文字特性变量插值 以$和@开头的变量被替换为实际变量的值.
大小写转换前缀 \l和\u把后面的一个字符转换为小写与大写.
大小写转换范围 \L和\U把后面的字符转换为小写和大写,作用范围一直到表达式末尾,或者\E为止.
文本文字范围 \Q把后面的字符当成本身,即转义元字符,作用范围到表达式末尾,或者\E为止.
不能转义表示变量插值的$与@,且通常用于变量插值内容的转义.\Q$string\E
动态作用域保存全局变量的副本,在代码块中修改此副本,退出代码块恢复原来的值.
正则表达式的伴随效应与动态作用域
正则表达式的伴随变量自动使用动态作用域.如 $1,$&,$`
特殊变量
$`
|
匹配文本之前的文本 |
$&
|
匹配文本 |
$'
|
匹配文本之后的文本 |
$1
|
第一组括号匹配的文本 |
$+
|
编号最大的括号匹配的文本(已匹配的括号) |
$^N
|
最后结束的括号匹配的文本(已匹配的括号) |
$-
|
匹配开始位置的偏移值数组 |
$+
|
匹配结束位置的偏移值数组
|
sub($text, $-[0], $+[0] - $-[0]) 等于 $&
括号捕获的区别
实例
|
$1
|
实例
|
$1
|
"::" =~ m/:(A?):/ |
空字符串 |
"::" =~ m/:(\w*):/
|
空字符串 |
"::" =~ m/:(A)?:/ |
undef |
"::" =~ m/:(\w)*:/ |
undef |
":A:" =~ m/:(A?):/ |
A |
":word:" =~ m/:(\w*):/ |
word |
":A:" =~ m/:(A)?:/ |
A
|
":word:" =~ m/:(\w)*:/ |
d
|
Regex对象qr// 返回regex对象.
对象的匹配模式不能在匹配时更改,已经被锁定在qr//中.
Match运算符scalar context
不使用 \g : 返回 true/false
使用 \g : 迭代匹配,只进行一次匹配,但下次匹配会从上次成功的匹配位置后开始匹配.
list context
不使用 \g : 返回list ,元素为捕获括号的值.如果没用捕获括号,返回 list (1).针对一次匹配
使用 \g : 返回list ,元素为捕获括号的值.如果没有捕获括号,返回整个匹配的文本.针对所有匹配.
/gc
匹配失败不会重置目标字符串的pos.
\G
不要启动驱动过程,如果在此匹配不成功,就报告失败.
/gc与\G常一起使用,创建词法分析器.
match运算符与pos的相互作用
匹配类型 |
尝试开始位置
|
匹配成功的pos值
|
匹配失败的pos值
|
m// |
字符串起始位置(忽略pos) |
重置为undef |
重置为undef |
m//g |
字符串的pos位置 |
匹配结束位置的偏移值 |
重置为undef |
m//gc |
字符串的pos位置 |
匹配结束位置的偏移值 |
不变 |
典例
print $& while "hello world" =~ m/\w+/g; # helloworld
print $& if "hello world" =~ m/\w+/g; # hello
print $& for "hello world" =~ m/\w+/g; # worldworld
Substitution运算符s/regex/replacement/modifiers,返回值为替换次数.
regex按照正则表达式的方式解析,repalcement按照普通的双引号字符串解析.
以下两种情况repalcement不按双引号字符串解析.
1.分隔符为单引号,此时作为单引号字符串解析.
2.modifiers为/e,replacement作为Perl代码执行,执行结果作为repalcement.
/e
把replcement作为Perl代码执行,类似eval{}.
/e如果多于一次,Perl将把求值的结果继续当成Perl代码求值.求值次数与e的个数一样多.
Split运算符split (match, string, chunk-limit) 根据match把string分隔成段返回list.chunk-limit表示切分的字符串数目上限.
默认返回开始的空元素,忽略结尾的空元素.可以通过修改 chunk-limit参数改变.
split / / 与 split /\s+/ 第一种基本同第二种,只是忽略开头的空元素.
Split不产生伴随效应.
带捕获括号的Split,将把match也作为list的元素返回.
Perl专有特性动态正则结构 (??{})
执行其中的Perl代码,把结果作为当前匹配的一部分即刻被应用.
内嵌代码结构 (?{})
执行其中的Perl代码,不需要返回值.
匹配嵌套结构使用动态正则结构,可以递归处理任意深度的嵌套.
my $levelN;
$levelN = qr/ \( ( [^()] | (??{ $levelN }) )* \)/x; 嵌套匹配任意深度的括号.
用内嵌代码显式所有匹配
"ab" =~ m{
\w+
(?{ print"$`<$&>$'\n"})
(?!)
}x;
结果为:
b
a
(?!)为否定型顺序环视,匹配必然失败,强迫引擎回溯,最后试遍所有可能.
差不多应该告一段落了 回去和兄弟伙们Dota了 !~
阅读(2506) | 评论(0) | 转发(0) |