GNU BRE正则表达式的正则表达式匹配引擎采用的匹配模型见《一种正则表达式匹配模型》。
由于GNU grep命令的默认模式使用GNU BRE正则表达式,因此本文接下来使用它进行实验。
特别需要强调的是,由于“locale设置”不同,操作系统环境不同等因素,同一个正则表达式可能具有不同的表达含义。比如在“locale=C”设置下,“[a-d]”等价于“[abcd]”,而在有些locale设置下,“[a-d]”等价于“[aBbCcDd]”。又比如只在有些locale设置中,“\w”等价于“[a-zA-Z_0-9]”,“\W”等价于“[^a-zA-Z_0-9]”才成立。
接下来的语法介绍只针对“一般情形”,而不针对“特殊情形”,为了确保在你的“具体情形”下,正则表达式能够如你所期望地进行表达,最好能够提前进行一些测试。
正则表达式中不同语法单元具有不同的优先级顺序,无需记忆,使用“匹配组(即\(\)
对)”方式更加清晰明了。
GNU BRE正则表达式跟GNU ERE正则表达式相比,表达能力几乎没有差别,主要差别在于:在GNU BRE正则表达式中,?+{}()|
等这些字符原生没有特殊含义,只有添加前导“\”字符后才具有特殊含义,以上差别导致了GNU ERE正则表达式相较于GNU BRE正则表达式更加简洁清晰。因此,在两者可选的情况下,一般选用GNU ERE正则表达式。
一、字符类
1.1、定义
字符类 | 定义 |
---|---|
[abc] | 匹配“a,b,c”3个字符之一 |
[^abc] | 匹配除了“a,b,c”3个字符之外的任意一个字符 |
[a-zA-Z] | 匹配26个小写英文字符和26个大写英文字符中的任意一个 |
[^a-z] | 匹配除了26个小写英文字符之外的任意一个字符 |
1.2、实验
有文件“a.txt”,内容如下:
1 | hello world |
执行命令 | 结果 |
---|---|
grep '[old]' a.txt |
hello world |
grep '[^old]' a.txt |
hello world this is an experiment |
grep '[x-z]' a.txt |
this is an experiment |
二、预定义字符类
2.1、定义
预定义字符类 | 定义 |
---|---|
. | 匹配任意字符,除了行终止符 |
\w | 等价于[a-zA-Z_0-9] |
\W | 等价于[^\w] |
2.2、实验
有文件“a.txt”,内容如下(第5行是个“TAB”字符):
1 | a$ |
执行命令 | 结果 |
---|---|
grep '.' a.txt |
a$ A$ 9$ _$ $$ |
grep '\w' a.txt |
a$ A$ 9$ _$ |
grep '\W' a.txt |
a$ A$ 9$ _$ $$ |
三、量词修饰符
3.1、定义
量词修饰符 | 定义 |
---|---|
X? | 匹配0次或者1次 |
X* | 匹配0次或者0次以上 |
X\+ | 匹配1次或者1次以上 |
X\{n\} | 匹配n次 |
X\{n,\} | 匹配至少n次 |
X\{,m\} | 匹配至多m次 |
X\{n,m\} | 匹配至少n次,至多m次 |
3.2、实验
有文件“a.txt”,内容如下(第1行是空行):
1 |
|
执行命令 | 结果 |
---|---|
grep 'a\?' a.txt |
a bb ccc |
grep 'a*' a.txt |
a bb ccc |
grep 'b\+' a.txt |
bb |
grep '.\{2\}' a.txt |
bb ccc |
grep '.\{1,\}' a.txt |
a bb ccc |
grep '.\{,2\}' a.txt |
a bb ccc |
grep '.\{2,3\}' a.txt |
bb ccc |
四、匹配组
4.1、定义
正则表达式中由“\(\)”对括起来的子表达式被称为“匹配组”,它作为独立的匹配单元参与匹配。在正则表达式中,“匹配组”的数量就是“\(\)”对的数量,“匹配组”的标号按照“\(”符号出现的先后顺序进行确定:从“1标号-匹配组”开始。也存在“0标号-匹配组”,它是特殊的“匹配组”,它代表整个正则表达式。比如有\(\(A\)\(B\(C\)\)\)
,其中“匹配组”数量为“4”,“1标号-匹配组”是“\(\(A\)\(B\(C\)\)\)”,“2标号-匹配组”是“\(A\)”,“3标号-匹配组”是“\(B\(C\)\)”,“4标号-匹配组”是“\(C\)”,“0标号-匹配组”是“\(\(A\)\(B\(C\)\)\)”;又有\(A\)\(B\(C\)\)
,其中“匹配组”数量为“3”,“1标号-匹配组”是“\(A\)”,“2标号-匹配组”是“\(B\(C\)\)”,“3标号-匹配组”是“\(C\)”,“0标号-匹配组”是“\(A\)\(B\(C\)\)”。
可通过“\匹配组标号”形式在正则表达式引用相应“匹配组”在目标字符串中的匹配字符串内容,需要注意的是,不能使用“\0”,因为这是“语义非法的”。证明如下:现有一个正则表达式“abc\0”(a,b,c分别表示3个部分),为使该正则表达式有意义,“abc”3部分至少有一个不为空,假定该正则表达式存在对应的匹配字符串T,由于“T”与“\0”匹配,而“abc”至少有一个不为空,得到一个矛盾,因此假定不成立,即该正则表达式无对应的匹配字符串。
4.2、实验
有文件“a.txt”,内容如下:
1 | abcabc |
执行命令 | 结果 |
---|---|
grep '\([a-z]\{3\}\)\1' a.txt |
abcabc |
grep '\([a-z]\{2\}\)c\1' a.txt |
abcabc abcabd |
五、边界匹配符
5.1、定义
边界匹配符 | 定义 |
---|---|
^ | 索引位置为“行首位置”,跟行终止符无关 |
$ | 索引位置为“行尾位置”,行终止符为“\n” |
< | 索引位置为“行首位置”,跟行终止符无关,跟“^”等价 |
\> | 索引位置为“行尾位置”,行终止符为“\r”或者“\n” |
\b | 索引位置为“单词边界位置” |
\B | 索引位置为“非单词边界位置” |
5.2、实验
有文件“a.txt”,内容如下:
1 | hello world |
执行od -A d -t x1cz -v -w10 a.txt
命令,结果如下:
1 | 0000000 68 65 6c 6c 6f 20 77 6f 72 6c |
有文件“b.txt”,内容如下:
1 | hello world |
执行od -A d -t x1cz -v -w10 b.txt
命令,结果如下:
1 | 0000000 68 65 6c 6c 6f 20 77 6f 72 6c |
执行命令 | 结果 |
---|---|
grep '\be' a.txt |
this is an experiment |
grep '\Bh\B' a.txt |
this is an experiment |
grep '^[ht]' a.txt |
hello world this is an experiment |
grep '^[ht]' b.txt |
hello world this is an experiment |
grep '\<[ht]' a.txt |
hello world this is an experiment |
grep '\<[ht]' b.txt |
hello world this is an experiment |
grep '[dt]$' a.txt |
hello world this is an experiment |
grep '[dt]$' b.txt |
|
grep '[dt]\>' a.txt |
hello world this is an experiment |
grep '[dt]\>' b.txt |
hello world this is an experiment |
六、转义
6.1、定义
在正则表达式中,使用前导“\”字符来转义元字符。元字符有[].^$*-
等。
6.2、实验
有文件“a.txt”,内容如下:
1 | a |
执行命令 | 结果 |
---|---|
grep '.' a.txt |
a . |
grep '\.' a.txt |
. |
七、操作符
7.1、定义
操作符 | 定义 |
---|---|
| | “或”操作符 |
7.2、实验
有文件“a.txt”,内容如下:
1 | ab |
执行命令 | 结果 |
---|---|
grep 'ab|dc' a.txt |
ab dc |
参考文献: [1]man grep [2]http://www.regular-expressions.info/gnu.html