0%

GNU ERE正则表达式

GNU ERE正则表达式的正则表达式匹配引擎采用的匹配模型见《一种正则表达式匹配模型》
由于GNU grep命令的“-E”模式使用GNU ERE正则表达式,因此本文接下来使用它进行实验。
特别需要强调的是,由于“locale设置”不同,操作系统环境不同等因素,同一个正则表达式可能具有不同的表达含义。比如在“locale=C”设置下,“[a-d]”等价于“[abcd]”,而在有些locale设置下,“[a-d]”等价于“[aBbCcDd]”。又比如只在有些locale设置中,“\w”等价于“[a-zA-Z_0-9]”,“\W”等价于“[^a-zA-Z_0-9]”才成立。
接下来的语法介绍只针对“一般情形”,而不针对“特殊情形”,为了确保在你的“具体情形”下,正则表达式能够如你所期望地进行表达,最好能够提前进行一些测试。
正则表达式中不同语法单元具有不同的优先级顺序,无需记忆,使用“匹配组(即()对)”方式更加清晰明了。

一、字符类

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 -E '[old]' a.txt hello world
grep -E '[^old]' a.txt hello world
this is an experiment
grep -E '[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 -E '.' a.txt a$
A$
9$
_$

$$
grep -E '\w' a.txt a$
A$
9$
_$
grep -E '\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 -E 'a?' a.txt
a
bb
ccc
grep -E 'a*' a.txt
a
bb
ccc
grep -E 'b+' a.txt bb
grep -E '.{2}' a.txt bb
ccc
grep -E '.{1,}' a.txt a
bb
ccc
grep -E '.{,2}' a.txt
a
bb
ccc
grep -E '.{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 -E '([a-z]{3})\1' a.txt abcabc
grep -E '([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 -E '\be' a.txt this is an experiment
grep -E '\Bh\B' a.txt this is an experiment
grep -E '^[ht]' a.txt hello world
this is an experiment
grep -E '^[ht]' b.txt hello world
this is an experiment
grep -E '\<[ht]' a.txt hello world
this is an experiment
grep -E '\<[ht]' b.txt hello world
this is an experiment
grep -E '[dt]$' a.txt hello world
this is an experiment
grep -E '[dt]$' b.txt
grep -E '[dt]\>' a.txt hello world
this is an experiment
grep -E '[dt]\>' b.txt hello world
this is an experiment

六、转义

6.1、定义

在正则表达式中,使用前导“\”字符来转义元字符。元字符有+{}|()?[].^$*-等。

6.2、实验

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

1
2
a
.
执行命令 结果
grep -E '.' a.txt a
.
grep -E '\.' a.txt .

七、操作符

7.1、定义

操作符 定义
| “或”操作符

7.2、实验

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

1
2
ab
dc
执行命令 结果
grep -E 'ab|dc' a.txt ab
dc

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