一个正则表达式包含下面一个或多个项:
1.一个字符集
这里的字符集里的字符表示的就是它们字面上的意思.正则表达式最简单的情况就是仅仅由字符集组成,而没有其他的元字符。
2.锚
一个锚指明了正则表达式在一行文本中要匹配的位置,例如^和$就是锚。
3.修饰符
它们用于展开或缩小(即是修改了)正则表达式匹配文本行的范围.修饰符包括了星号、括号和反斜杠符号。
* 匹配重复零次或多次前一字符
+ 匹配一个或多个前面的字符.它的作用和*很相似,但唯一的区别是它不匹配零个字 符的情况 (扩展元字符)
? 匹配零或一个前面的字符。它一般用于匹配单个字符 (扩展元字符)
. 匹配任意字符( 除换行符 )
^ 匹配一行的开头,但依赖于上下文环境,可能在正则表达式中表示否定一个字符 集的意思
[...] 匹配集合中任意字符 如"[xyz]" 匹配字符 x, y, 或z
[^...] 匹配不属集合 中 任意字符
^, $ 匹配 行首、行尾
\<, \> 用于表示单词的边界。\< 匹配词首,\>词尾,如"\<the\>" 匹配单词"the"
\(...\) 正则表达式分组。进行子字符串提取(substring extraction)一起使用很有用
\n 第 n 个分组内容
\ 转义(escapes) 一个特殊的字符,使这个字符表示原来字面上的意思。"\$"表示 了原来的字面意思"$",而不是在正则表达式中表达的匹配行尾的意思."\\"也被 解释成了字面上的意思"\"
\{ \} 指示前面正则表达式匹配的次数.
要转义是因为不转义的话大括号只是表示他们字面上的意思.这个用法只是技巧上 的而不是基本正则表达式的内容."[0-9]\{5\}" 精确匹配5个数字(从0到9的数字).
| "或",正则操作符用于匹配一组可选的字符 (扩展元字符)
{n} n是一个非负整数。匹配确定的n次。例如,''o{2}'' 不能匹配 "Bob"中的''o'',但是能匹配"food" 中的两个o。(扩展元字符)
{n,} n是一个非负整数。至少匹配n次。例如,''o{2,}'' 不能匹配"Bob"中的'o'',但能匹配 "foooood"中的所有o。''o{1,}''等价于''o+''。''o{0,}''则等价于''o*''。(扩展元字符)
{n,m} m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,"o{1,3}"将匹配 "fooooood"中的前三个o。''o{0,1}''等价于''o?''。请注意在逗号和两个数之间不能有空格。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如,''er\b'' 可以匹配"never" 中的''er'',但不能匹配 "verb"中的 ''er''。
\B 匹配非单词边界。''er\B''能匹配"verb"中的''er'',但不能匹配"never"中的 ''er''
\w 匹配包括下划线的任何单词字符。等价于''[A-Za-z0-9_]''。
\W 匹配任何非单词字符。等价于''[^A-Za-z0-9_]''。
\d 匹配一个数字字符。等价于[0-9]。
\D 匹配一个非数字字符。等价于[^0-9]。
\f 匹配一个换页符。等价于\x0c和\cL。
\n 匹配一个换行符。等价于\x0a和\cJ。
\r 匹配一个回车符。等价于\x0d和\cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[\f\n\r\t\v]。
\S 匹配任何非空白字符。等价于[^\f\n\r\t\v]。
\t 匹配一个制表符。等价于\x09 和 \cI。
\v 匹配一个垂直制表符。等价于\x0b和\cK。
常用的就介绍到这里,其它的需要进一步了解可以查阅手册或资料。
元字符集
^
锚定行的开始 如:/^sed/匹配所有以sed开头的行。
$
锚定行的结束 如:/sed$/匹配所有以sed结尾的行。
.
匹配一个非换行符的字符 如:/s.d/匹配s后接一个任意字符,然后是d。
*
匹配零或多个字符 如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行。
[]
匹配一个指定范围内的字符,如/[Ss]ed/匹配sed和Sed。
[^]
匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。
\(..\)
保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers。
&
保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。
\<
锚定单词的开始,如:/\<love/匹配包含以love开头的单词的行。
\>
锚定单词的结束,如/love\>/匹配包含以love结尾的单词的行。
x\{m\}
重复字符x,m次,如:/0\{5\}/匹配包含5个o的行。
x\{m,\}
重复字符x,至少m次,如:/o\{5,\}/匹配至少有5个o的行。
x\{m,n\}
重复字符x,至少m次,不多于n次,如:/o\{5,10\}/匹配5–10个o的行。
部分例子
/\b([a-z]+)\1\b/gi 一个单词连续出现的位置
/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/ 将一个URL解析为协议、域、端口及相对路径
http
/^(?:Chapter|Section) [1-9][0-9]{0,1}$/定位章节的位置
/[-a-z]/ A至z共26个字母再加一个-号。
/ter\b/ 可匹配chapter,而不能terminal
/\Bapt/ 可匹配chapter,而不能aptitude
/Windows(?=95 |98 |NT )/ 可匹配Windows95或Windows98或WindowsNT,当找到一个匹配后,从Windows后面开始进行下一次的检索匹配。
下面来些更加高级些的例子。
对于vi 中命令的分析
s/\(^.*$\)\n^.*$/\1/g
初一看,会傻眼,眼前感觉全是$^.*/\……这些符号的闪动。
不要紧,下面慢慢道来。
先给出vi中替换命令的格式。
s/re/string 用string替换正则表达式re
如果在后面加了个g 如: s/re/string/g
表示表示对该行内符合模式的进行全部替换。
例如,s/\//_/g 这个正则表达式就表示,对行内所有的斜扛(/)替成下划线(_),\ /即替换命令格式中的re,用反斜扛\是为了转义,\ /即表示 / 的本意;_即替换命令格式中的string。
好了,了解vi中替换命令的格式后,我们再对细节进行分析。
前面介绍到 \(...\) 表示正则表达式分组,\n表示第 n 个分组内容,于是对于
s/\(^.*$\)\n^.*$/\1/g
中的 \1 ,就表示第一个正则表达式分组即\(^.*$\),我们暂将第一个正则表达式分组\(^.*$\)其记为:A
类推,\2就应该表示第二个正则表达式分组,即 \n^.*$ 实际上 也应该写在括号内比较好:\(\n^.*$\) ,我们也暂将第二个正则表达式分组 \n^.*$ 记为:B
好了,
%s/\(^.*$\)\n^.*$/\1/g
就可以写为:
s/AB/A/g
作用就是将行内所有的AB都替换成A。
现在我们来分别分析A和B的作用。
A=\(^.*$\)
抽取出来实际上是\(...\),表示正则表达式 分组,再分析括号内的^.*$,^代表行首,点号(.)匹配任意字符(除换行符),星号(*)匹配重复零次或多次前一字符,$代表匹配到行尾,综合起来就是:匹配这一行
B=\n^.*$
分析: \n换行,^.*$同上,表示匹配这一行,综合起来就是:下一行(即上行结束后开始的另一行)。
再于是就有:%s/AB/A/g 即将所有AB都替换成B ,代入A和B各自意思得到:
将两行(如行1和行2 )内容替换为第一行内容(即行1的内容),加上/g,就是对全文进行前述替换,也就是隔行删除,如果是从文件第一行开始进行的操作,就意味着是删除所有偶数行、保留所有奇数行操作。
从上面的分析过程中,我们总结出两条有用的正则表达式:
%s/\(^.*$\)\n^.*$/\1/g 删除偶数行
%s/^.*$\n\(^.*$\)/\1/g 删除奇数行
不过瘾的话,还可以再看看另一例子:
sed 's/\(.*\)\(.\)$/\2/'
\2就应该表示第二个正则表达式分组
同上,也将A=/\(.*\),B=\(.\)$,表达式变为's/AB/B',将AB都替换成B 。
分析A、B作用。
A=/\(.*\)
抽取出来实际上是\(...\),表示正则表达式 分组,再分析括号内的 .*,表示匹配任意零个或多个字符 ( 除换行符 )
B=\(.\)$
括号内的 . ,表示匹配任意字符(除换行符) ,括号外的$表示匹配到行尾,即表示行尾的最后一个字符;那上述的A /\(.*\) 就表示该行最后一个字符前的所有字符。
于是sed 's/\(.*\)\(.\)$/\2/' 作用就是:删除该行除最后一个字符外的所有字符,保留最后一个字符,也即取得该行最后一个字符。
好了,正则表达式的介绍就告一段落,知识点比较多,需要平时反复的积累,遇到复杂的正则表达式时首先要克服恐惧的心理,然后按照上面的方法化繁为简,抓住其本质的东西,有如探囊取物,必手到擒来。