Unix支持两种的正则表达式的版本:
(1)现代版本:扩展正则表达式(extended regular expression,ERE),属于IEEE1003.2标准,拥有比BRE更多的功能。
(2)废弃版本:基本正则表达式(basic regular expression,BRE),它是多年以前使用的更原始类型的正则表达式,功能弱且语法容易混淆,后来被1003.2标准取代,保留它们只是为了与旧程序兼容。
ERE和BRE之间的主要区别:对于BRE来说,有一些特定的元字符不能使用,而其他元字符必须使用反斜线引用。不能使用的元字符有问号、加号和竖线
? + |
必须转义的元字符有花括号和圆括号
{ } ( )
基本正则表达式的限制:
Ø 花括号必须使用反斜线引用,如\{\}
Ø 圆括号必须使用反斜线引用,如\(\)
Ø 不能使用?,但是可以使用\{0,1\}模拟
Ø 不能使用+,但是可以使用\{1,\}模拟
Ø 不能使用|(竖线)
Ø 不能使用预字义字符类
1. 所有的普通字符,例如字母和数字都与自身匹配,如shell匹配于shell;WoRd匹配于WoRd,但不匹配于word
2. 当我们需要表示meta字符本身时,可以转义它,即前面放一个反斜杠。例如
\* 匹配字面上的*
\\ 匹配字面上的\
3. 在方括号表达式中,所有其他的的meta字符都会失去其特殊含义,例如
[ .\*]匹配于句点、反斜杠及星号。
4. 为了扩展正则表达式的功能,可以使用锚指定查找模式的位置。如$元字符是一个匹配行末尾的锚。为了搜索以“xiao“结尾的行,可以使用:
grep ‘xiao$’ data
通过使用这^ $这两个锚,但是两个锚之间不指定任何内容何以方便地查找空行。
grep ‘^$ ’ data | wc -l
匹配包含一个字符的行
grep ‘^.$’ data
注意:^与$仅在BRE的起始与结尾下有特殊用途。
查找所有包含字符串”kn”的行,但是字符串kn只能出现在单词的开头
grep ‘\<kn’ data
为了搜索完整的单词,可吧同时使用\<和\>
grep ‘\<word\> data
为了方便起见,在使用GNU实用工具的系统上,如Linux和FreeBSD系统,可以使用\b(boundary marker ,边界标记)作为\<和\>的替代,
grep ‘\<word\> data = grep ‘\bword\b’ data
以下由高至低列出了ERE运算符的优先级:
运算符 |
含义 |
[ . . ] [ = =] [ : : ] |
用于字符对应的方括号符号 |
\metacharacter |
转义的元字符 |
[ ] |
方括号表达式 |
( ) |
分组 |
+ * ? { } |
重复前置的正则表达式 |
无符号(no symbol) |
连续字符 |
^ $ |
锚点 |
| |
交替 |
运算符 |
含义 |
\w |
匹配任何单词组成字符,等同于[[:alnum:]] |
\W |
匹配任何非单词组成字符,等同于[^[:alnum:]] |
\< \> |
匹配单词的起始与结尾 |
\b |
匹配单词的起始或结尾处所找到的空字符串。注意:由于awk使用\b表示后退字符,因此GNU awk(gawk)使用\y表示此功能 |
\B |
匹配两个单词组成字符之间的空字符串 |
|
|
在正则表达式中,元字符.(点号)匹配任何单个的字符,新行字符除外(在Unix中,新行字符标记一行的末尾)
例:grep ‘xiao..y’ data
在data文件中查找所有包含下述模式的行:字符串xiao后跟两个任意字符,再后跟一个字母y
字符类:将字符放在方括号[]中指定希望搜索的字符。这样的结构就称为一个字符类。
grep ‘\\\*.*[A-Za-z]+\$’ data
查找所有包含字符“\*”,后面跟任意数量的字符,再后跟1 个或多个字母,最后跟一个“$”的行。
怎样理解复杂的正规表达式
当遇到难以理解的正则表达式时,将它写在一张纸上,然后将正则表达式分成不同部分,纵向书写不同部分,一个在另一个之上。依次取不同部分,并将各部分的含义写在同一行上。
我们将这个正则表达式分隔成:
\\ _____ 1个\(反斜线)字符
\* —— 1个*(星号)字符
.* ____ 任意数量的其他字符
[A-Za-z] ____ 1 个或多个大写字母或小写字母
\$ ____ 1个$(美元)字符
示范文件:Linux中的字典文件/usr/share/dict/words
(1)哪些英语单词以“qu”开头并以y结尾呢?
grep ‘^yu[a-z]+y$’ /usr/share/dict/words
grep '^qu.*y$' /usr/share/dict/words^ 行的开头
egrep '^yu[a-z]+y$' /usr/share/dict/words
qu 字符串qu
[a-z]+ 1个或多个小写字母
y 字母y
$ 行的结尾
(2)查找一个包含所有5个元间字母a、e、i、o、u(并且以该顺序出现)的普通英语单词。
这5个字母不必连在一起,但是它们必须按字母表顺序出现
grep 'a[a-z]*e[a-z]*i[a-z]*o[a-z]*u' /usr/share/dict/words
(3)在/bin目录中查找包含两个字母长的命令
ls /bin | egrep '^[a-z]{2}$'
ls /bin | grep '^[a-z][a-z]$'
注:在一些系统上,grep并不会返回预想的结果,因为它不能将括号识别为花括号元字符,如果出现这种情况,可以使用egrep 代替grep