正则表达式基础
Linux Shell以字符串作为表达式向系统传达意思。元字符(Metacharacters)是用来阐述字符表达式意义的字符,是描述字符的字符,它用于对字符表达式的内容、转换及各种操作信息进行描述。正则表达式是由一串字符和元字符构成的字符串,简称RE(Regular Expression)。正则表达式的主要功能是文本查询和字符串操作,它可以匹配文本的一个字符或字符集合。
POSIX标准将正则表达式分为两类:基本的正则表达式和扩展的正则表达式,大部分Linux应用和工具仅支持基本的正则表达式。基本的正则表达式元字符集合及其意义如下:
| 符号 | 意义 |
|---|---|
| * | 0个或多个在*字符之前的那个普通字符 |
| . | 匹配任意一个字符 |
| ^ | 匹配行首,或后面字符的非 |
| $ | 匹配行尾 |
| [] | 匹配[]内字符集合里的一个字符 |
| 转义字符,屏蔽一个元字符的特殊意义 | |
| <> | 精确匹配符号 |
| {n} | 匹配前面字符出现n次 |
| {n,} | 匹配前面字符至少出现n次 |
| {n,m} | 匹配前面字符出现n~m次 |
1. *符号
*符号用于匹配前面一个普通字符的0次或多次重复。例如hel*o匹配helo、hello、helllo等。
2. .符号
.符号用于匹配任意一个字符。例如,...73.表示前三个字符为任意字符,第4个字符是'7',第5个字符是'3',最后一个字符为任意字符,如xcb738、4J973U都能匹配。需要注意,.符号可以匹配空格。因此x b738、ui 73e也能匹配。
3. ^符号
^符号用于匹配行首。行首的第一个字符是^后面那个字符。例如,^cloud表示匹配以cloud开头的行。再举一个例子,^...X86*表示行首的前三个字符为任意字符(可以是空格),第4~6个字符为X86,第7个字符开始可以重复匹配6,866X86666、8 6X86等都可以匹配。
4. $符号
$符号匹配行尾,,与^符号的功能和用法都相反。例如micky$表示匹配以micky结尾的行。一个特殊的正则表达式是匹配空行。如下所示:
^$
该正则表达式既匹配行首,又匹配行尾,中间没有任何字符,所以匹配空行。很多命令都用到这个正则表达式来匹配空行。
5. []符号
[]符号匹配字符集合,该符号支持穷举方法列出字符集合的所有元素,也支持使用-表示字符集合范围。字符集合范围从-左边字符开始,到-右边字符结束。下面举例说明[]用法:
#匹配任意一个数字
[0123456789] #直接穷举
[0-9] #用范围表示,比较简洁
#匹配字母
[a-z] #所有小写字母
[A-Z] #所有大写字母
[b-p] #小写字母b到p
[a-zA-Z] #匹配一个小写字母或大写字母
[a-zA-Z]* #匹配任意个小写字母或大写字母
我们已经知道,^符号表示匹配行首,但当^符号放到[]符号中就不再表示匹配行首,而是取反符号。例如,[^b-d]表示匹配不在bd范围之内的字符。此时,`^`符号不在表示匹配行首,而是取反符号,不在bd范围内的字符涵盖了除了小写字母b、c和d之外的所有字符(包括其他字母、数字、空格等)。
6. 符号
符号是转义字符,用于屏蔽一个元字符的特殊含义,即以字面意义来解释符号后面的字符。例如,.表示匹配字符.。
7. <>符号
<>符号是精确匹配符号,该符号利用符号屏蔽<>符号的特殊意义。例如,<the>表示精确匹配the,而不匹配包含the的字符串,如them、there、another等。
8. {}符号
{}符号与*符号很类似,都表示前一个字符的重复。不同的是,*符号表示重复0次或多次,而{}符号可以指定重复次数。示例如下:
jo{3}b #重复字符o 3次,匹配jooob
jo{3,}b #重复字符o 至少3次,匹配jooob、joooob、jooooob等
jo{3,6}b #重复字符o 3~6次,匹配jooob、joooob、jooooobjoooooob
[a-z]{5} #表示匹配五个小写字母
正则表达式的扩展
除了基本的正则表达式之外,awk和perl等Linux工具还支持正则表达式扩展出来的一些元字符。扩展的正则表达式元字符及其意义如下:
| 符号 | 意义 |
|---|---|
| ? | 匹配0个或1个在它前面的一个字符 |
| + | 匹配1个或多个在它前面的一个字符 |
| () | 表示一个字符集合或或用在表达式中 |
| ` | ` |
示例如下:
jo?b #匹配job、joob
S+EU #匹配SSEU、SSSEU、SSSSEU等,但不能匹配SEU
()符号通常与|符号结合使用,表示一组可选字符的集合。例如re(a|e|o)d中的(a|e|o)表示在a、e和o中选择一个字符进行匹配,因此re(a|e|o)d匹配read、reed、reod。事实上,()符号很少被用到,因为[]符号能够替代()符号表示一组可选字符的集合,re(a|e|o)d就等价于re[aeo]d。
|符号也可以表示多个正则表达式的“或”关系,格式如下:
RE1 | RE2 | RE3 | ... #RE1、RE2、RE3表示正则表达式
|符号在扩展的正则表达式中表示“或”的这种用法很少有人记得,|符号最著名的用法是作为管道符号。
通配
bash Shell本身并不支持正则表达式,支持正则表达式的是一些命令和工具,如grep、sed、awk等,但是bash Shell支持通配(Globbing)功能,通配是把一个包含通配符的非具体文件名扩展到存储在计算机、服务器或者网络上的一批具体文件名的过程。掌握通配符的使用有助于简化一些问题的处理步骤。Shell常见通配符如下:
| 字符 | 含义 |
|---|---|
| * | 匹配任意多个字符 |
| ? | 匹配一个字符 |
| [] | 匹配[]内字符集合里的一个字符 |
| ^ | 匹配结果取反,与[]配合使用 |
| {} | 匹配括号内包含的一个或多个字符串 |
示例如下:
*.awk #匹配以.awk结尾的文件
0?.pem #匹配以0开头、后面有一个字符且以.pem结尾的文件
[a-h]*.awk #匹配以a~h范围内的字母开头,并以.awk结尾的文件
[^a-h]* #匹配不以a~h范围内字母开头的文件
{0?.pem,[a-h]*.awk} #匹配以0开头、后面有一个字符且以.pem结尾的文件或者以a~h范围内的字母开头,并以.awk结尾的文件
grep命令
grep是Globally search Regular Expression and Print out the line的简称,即全面搜索正则表达式,并把行打印出来。grep是一种强大的文本搜索工具,它使用正则表达式搜索文本,并把匹配的行打印出来。grep命令格式如下:
grep [选项] [模式] [文件...]
常用grep命令选项及其意义如下:
| 选项 | 意义 |
|---|---|
| -c | 只输出匹配行的数量(默认情况下,grep命令打印出匹配模式的所有行) |
| -i | 搜索时忽略大小写(默认情况下,区分大小写) |
| -h | 查询多文件时不显示文件名(默认情况下,grep命令搜索多个文件时,在匹配行之前显示文件名) |
| -l | 只列出符合匹配的文件名,而不列出具体的匹配行 |
| -n | 列出匹配行,并显示行号(默认情况下,grep命令搜索单个文件时,只显示匹配行的内容;搜索多个文件时,显示文件名和匹配行的内容。加上-n选项后,将在行内容前显示行号) |
| -s | 不显示文件不存在或无匹配文本的错误信息(默认情况下,grep命令在待搜索文件不存在或搜索不到匹配模式的文本行时打印错误信息) |
| -v | 显示不匹配模式的所有行(相当于取反) |
| -m num | 匹配num次后停止 |
| -w | 匹配整词 |
| -x | 匹配整行 |
| -r | 递归搜索,不仅搜索当前目录,而且搜索子目录(默认情况下,grep命令只对当前目录下的文件进行搜索) |
| -q | 不输出任何结果,以退出状态表示是否搜索成功。退出状态0表示搜索成功,退出状态1表示未搜索到满足模式的匹配行,退出状态2表示命令或程序由于错误未能执行 |
| -b | 输出匹配行距文件头部的偏移量,以字节为单位 |
| -o | 与-b选项结合使用,输出匹配的词距文件头部的偏移量,以字节为单位 |
| -E | 支持扩展的正则表达式(grep -E相当于egrep) |
| -F | 不支持正则表达式,按字符串字面意思进行匹配(grep -F相当于fgrep) |
两个讲解grep命令例子如下:
现在我们回顾一下find命令:
- 功能:在目录结构中搜索文件,并执行指定的操作。此命令提供了相当多的查找条件,功能很强大。
- 语法:
find 起始目录 寻找条件 操作 - 说明:find命令从指定的起始目录开始,递归地搜索其各个子目录,查找满足寻找条件的文件并对之采取相关的操作。
所以grep和find的区别简单来讲,grep是查找匹配条件的行,find是搜索匹配条件的文件。
为了保持不同国家的字符编码的一致性,POSIX(Portable Operating System Interface of UNIX)增加了POSIX字符类。grep命令支持POSIX字符类。常见POSIX字符类如下:
| 类名 | 意义 |
|---|---|
| [:upper:] | 大写字母[A-Z] |
| [:lower:] | 小写字母[a-z] |
| [:digit:] | 阿拉伯数字[0-9] |
| [:alpha:] | 大小写字母[A-Za-z] |
| [:alnum:] | 大小写字母和阿拉伯数字[A-Za-z0-9] |
| [:space:] | 空格或Tab键 |
| [:cntrl:] | Ctrl键 |
| [:graph:]或[:print:] | ASCII码在33~126之间的字符 |
| [:xdigit:] | 十六进制数字[0-9A-Fa-f] |