从根本来看,正则表达式是由两个基本组成部分所建:一般字符与特殊字符。一般字符指的是任何没有特殊意义的字符,正如下表中所定义的。在某些情况下,特殊字符也可以视为一般字符。特殊字符常称为源字符。
字符 | 模式含义 |
---|---|
\ |
通常用以关闭后续字符的特殊意义。有时则是相反地打开后续字符的特殊意义,例如\(...\)与{...\} 。 |
. | 匹配任何单个字符,但NULL除外。独立程序也可以不允许匹配换行字符。 |
* | 匹配在他之前的任何数目(或没有)的单个字符。以ERE为例,此前置字符可以是正则表达式,例如.代表“匹配任一字符的任意长度”。以BRE来说,若置于正则表达式的第一个字符,不具有任何特殊意义 |
^ | 匹配紧接着的正则表达式,在行或字符串的起始处。BRE:仅在正则表达式的开头处具此特殊含义,ERE:置于任何位置都具有特殊含义 |
$ | 匹配前面的正则表达式,在字符串或行结尾处。BRE:仅在正则表达式结尾处具有特殊含义。ERE:置于任何位置都具有特殊含义 |
[…] | 方括号表达式,匹配方括号中的任一字符。连字符(-)指的是连续字符的范围。^符号置于方括号里第一字符则有反向含义:指的是匹配不再列表内(方括号内)的任何字符。作为首字符的一个连字符或是结束方括号(]),则被视为列表的一部分。所有其他的元自符也成为列表的一部分。 |
\{n,m\} |
区间表达式,匹配在他前面的单个字符重现的次数区间。\{n\}指的是重现n次;\{n,\}则为至少重现n次,而\{n,m\}为重现n至m次。 |
\( \) |
将\(和\) 之间的模式存储在特殊的”保留空间”。最多可以将9个独立的子模式存储在单个模式中。匹配于子模式的文本,可通过转移序列\1至\9,被重复使用在相同模式里。例如\(ab\).*\1 ,指的是匹配于ab组合的两次重现,中间可存在任何数目的字符 |
\n | 重复在“`(和)方括号内第n个子模式至此点的模式。n为1至9的数字,1由左开始. |
{n,m} | 与先前提到的BRE的\{n,m\} 一样,只不过方括号前没有反斜杠。 |
+ | 匹配前面正则表达式的一个或多个实例。 |
? | 匹配前面正则表达式的零个或一个实例。 |
“` | “` |
() | 匹配于括号括起来的正则表达式群 |
简单的正则表达式匹配范例
表达式 | 匹配 |
---|---|
tolstoy | 位于于一行上任何位置的7个字母:tolstoy |
^tolstoy | 7个字母tolstoy,位于一行的开头 |
tolstoy$ | 7个字母tolstoy,出现在一行的结尾 |
^tolstoy$ | 正好包括tolstoy这7个字母的一行,没有其他的人和字符 |
[Tt]olstoy | 在一行上任意位中,含有Tolstoy或tolstoy |
tol.toy | 在一行的任意位中,含有tol这3个字母,加上任何一个字符,再接着toy这3个字母 |
tol.*toy | 在一行上的任意位中,含有tol这三个字母,加上任意的0个或多个字符,再继续toy这三个字母(例如,toltoy,tolstoy,tolWHOtoy等) |
POSIX方括号表达式
字符集:[:和:]将关键字组合起来的POSIX字符集。关键字描述各种不同的字符集。
排序符号:排序符号指的是将多字符序列视为一个单位。它使用[.与.]将字组合括起来。排序符号在系统所使用的特定locale上各有其定义。
等价字符集:等价字符集列出的是应视为等职的一组字符,它由取自于locale的名字元素组成,以[=与=]括住。
这三种构造都必须使用方括号表达式。例如[[:alpha:]!]匹配了任一英文字母字符或惊叹号(!);然而[[.ch.]]则匹配于ch(排序元素),但字母c或h则不是。
POSIX字符集
类别 | 匹配字符 |
---|---|
[:alnum:] | 数字字符 |
[:alpha:] | 字母字符 |
[:blank:] | 空格(space)与定位(tab)字符 |
[:cntrl:] | 控制字符 |
[:digit:] | 数字字符 |
[:graph:] | 非空格字符 |
[:lower:] | 小写字母字符 |
[:print:] | 可显示字符 |
[:punct:] | 标点符号字符 |
[:space:] | 空白字符 |
[:upper:] | 大写字母字符 |
[:xdigit:] | 十六位进制数 |
基本正则表达式
1.匹配单个字符
将特殊字符以meat字符表示。
若meta字符不能表示它们自己,那当我们需要让meta字符表示他们自己的时候,那该怎么办?答案是转义它。在前面放一个反斜杠来做到这一点。因此,*匹配字面上的*,\匹配于字面上的反斜杠。
.(点号)字符即“任一字符”。因此,a.c匹配于abc,aac以及aqc。单个点号用以表示自己的情况很少。
最后一种匹配单个字符的方式是使用方括号表达式。最简单的方括号表达式就是直接将字符列表放在括号里,例如,[aeiouy]表示的就是所有小写元音字母。举例来说,c[aeiou]t匹配于cat,cot,cut等括号内有的字母。在方括号表达式里,^放在字首是取反的意思,也就是说,不在方括号列表里的任意字符。
将所有要匹配的字母全部列出来是一件无聊又麻烦的事情。例如[0123456789]指所有数字,就可以以[0-9]来表示。
排序是指给予成组的项目排列顺序的操作。一个POSIX的排序元素由当前locale中的元素名组成,并由[.与.]括起来。例如[ab[.ch.]de]则匹配于字符a,b,d,e或成对的ch;单独的c或h字符则不匹配。
在方括号表达式中,所有其他的meta字符都会失去其特殊含义。所以[*.]匹配于字面上的星号,反斜杠以及句点。要让]进入该集合,为了防止二义性的原因我们可以将它放在列表的最前面:
[]*\.]
,这样可以防止[]产生的二异性。至于-也为了区分与前面讲过的例子[0-9]的二异性,我们将其写到最前面[-*\.]
。如果同时存在]和-则可以写成这样:[]*\.-]
。
2.后向引用
BRE提供一种叫后向引用的机制,指的是“匹配于正则表达式匹配先前的半部分”(先前在\( 与 \)之间的表达式也需要匹配,而这类表达式在后面可以使用\n来进行匹配,n为表达式的顺序,第一个出现的表达式用\1代替。eg:\(abc\)\(123\)\2\1匹配的就是abc123123abc
);
后向引用在寻找重复字以及匹配引号时特别好用:
\(["']\).*\1
匹配以单引号或双引号括起来的字,例如’foo’,”bar”
3.单个表达式匹配多个字符
虽然.(点号)meta字符与方括号表达式都提供了一次匹配一个字符的很好的方法,但正则表达式真正强有力的功能,其实是在修饰符meta字符的使用上。这类meta字符紧接在具有单个字符的郑则表达式之后,且他们会改变正则表达式的含义。最常用的修饰符为星号(*)。表示“匹配0个或多个前面的单个字符”。因此,ab*c表示的是“匹配1个a,0或多个b字符以及a c”。则这个正则表达式匹配的有ac,abc,abbc等。(“匹配0个或多个”不代表匹配其他的某一个……,所以对应的adc并不匹配上一个)。
修饰符是好用,但它没有限制,你不能用*表示”匹配三个字符,而不是四个字符“,而要使用一个复杂的方括号表达式,表明所要匹配的次数。区间表达式便可以解决,他是将一个或两个数字,放在{ 和 }之间,有三种变化,如下:
\{n\} 前置正则表达式所得的结果重现n次
\{n,\} 前置正则表达式所得的结果重现至少n次
\{n,m\} 前置正则表达式所得的结果重写n至m次
比如a\{5\}对aaaaa匹配,q\{10,42\}就是匹配10到42个q。
n和m的值必须介于0至RE_DUP_MAX之间。RE_DUP_MAX是POSIX定义的符号型常数,且可通过getconf命令取得:
$ getconf RE_DUP_MAX
32767
4.文本匹配锚点
我们将^ 和 $两个meta字符叫做锚点,因为其用途在限制正则表达式匹配时,针对要被匹配字符串的开始或者结尾处进行匹配。
eg:
以abcABCdefDEF为例进行匹配的范例。
模式 | 是否匹配 | 匹配失败理由 |
---|---|---|
^ABC | 否 | 限定匹配的字符必须在起始处 |
^[[:alpha:]]\{3\} |
是 | 与开始的三个字符匹配 |
def$ | 否 | 限制匹配的字符必须在结尾处 |
DEF$ | 是 | 与结尾的三个字符匹配 |
^与$可以同时使用,它可以用来匹配空的字符串或行列。例如在grep加上-v选项可以用来显示所有不匹配于模式的行,使用上面的做法,便可以过滤掉文件里面的空行。
eg:
$ cat a.c
$ cat a.c | grep -v '^$'
他们的区别就是第一个命令会打印处空白行,而第二个命令不打印空白行。
5.BRE运算符优先级
运算符 | 表示意义 |
---|---|
[..] [==] [::] | 用于字符安排的方括号符号 |
\meta | 转义的meta字符 |
[] | 方括号表达式 |
\{ \} \digit |
字表达式与后向引用 |
* \{ \} |
前置单个字符重现的正则表达式 |
无符号(no symbol) | 连续 |
^ $ | 锚点 |