0%

GNU BRE正则表达式

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
2
hello world
this is an experiment
执行命令 结果
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
2
3
4
5
6
a$
A$
9$
_$

$$
执行命令 结果
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
2
3
4

a
bb
ccc
执行命令 结果
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
2
abcabc
abcabd
执行命令 结果
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
2
hello world
this is an experiment

执行od -A d -t x1cz -v -w10 a.txt命令,结果如下:

1
2
3
4
5
6
7
8
9
0000000  68  65  6c  6c  6f  20  77  6f  72  6c
h e l l o w o r l >hello worl<
0000010 64 0a 74 68 69 73 20 69 73 20
d \n t h i s i s >d.this is <
0000020 61 6e 20 65 78 70 65 72 69 6d
a n e x p e r i m >an experim<
0000030 65 6e 74 0a
e n t \n >ent.<
0000034

有文件“b.txt”,内容如下:

1
2
hello world
this is an experiment

执行od -A d -t x1cz -v -w10 b.txt命令,结果如下:

1
2
3
4
5
6
7
8
9
0000000  68  65  6c  6c  6f  20  77  6f  72  6c
h e l l o w o r l >hello worl<
0000010 64 0d 0a 74 68 69 73 20 69 73
d \r \n t h i s i s >d..this is<
0000020 20 61 6e 20 65 78 70 65 72 69
a n e x p e r i > an experi<
0000030 6d 65 6e 74 0d 0a
m e n t \r \n >ment..<
0000036
执行命令 结果
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
2
a
.
执行命令 结果
grep '.' a.txt a
.
grep '\.' a.txt .

七、操作符

7.1、定义

操作符 定义
&#124; “或”操作符

7.2、实验

有文件“a.txt”,内容如下:

1
2
ab
dc
执行命令 结果
grep 'ab&#124;dc' a.txt ab
dc

参考文献: [1]man grep [2]http://www.regular-expressions.info/gnu.html
您的支持将鼓励我继续分享!