详解正则表达式

详细说明的基本正则表达式和拓展正则表达式

正则表达式

简介

定义:

由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意义,而表示控制或通配的功能,类似于增强版的通配符功能,但与通配符不同,通配符功能是用来处理文件名,而正则表达式是处理文本内容中字符

分类:

  • 基本正则表达式:BRE Basic Regular Expressions
  • 扩展正则表达式:ERE Extended Regular Expressions

通配符与正则表达式的区别

通配符多用在文件名上,比如查找find,ls,cp,等等

在文本过滤工具里,都是用正则表达式,比如像awk,sed,等,是针对文件的内容的

基本上解释就是通配符是配合系统命令使用,一般用来匹配文件名

正则表达式是操作字符串,以行为单位来匹配字符串使用的。

注意:在通配符和正则表达式中有其不一样的地方,在通配符中可以匹配任意的0个或多个字符,而在正则表达式中他是重复之前的一个或者多个字符,不能独立使用的。比如通配符可以用来匹配任意字符,而正则表达式不行,他只匹配任意长度的前面的字符。

基本正则表达式元字符

字符匹配

.           #匹配任意单个字符,可以是一个汉字
[]          #匹配指定范围内的任意单个字符,示例:[wang]  [0-9]  [a-z]  [a-zA-Z]
[^]         #匹配指定范围外的任意单个字符,示例:[^wang]

[:alnum:]   #字母和数字
[:alpha:]   #代表任何英文大小写字符,亦即 A-Z, a-z
[:lower:]   #小写字母,示例:[[:lower:]],相当于[a-z]
[:upper:]   #大写字母
[:blank:]   #空白字符(空格和制表符)
[:space:]   #包括空格、制表符(水平和垂直)、换行符、回车符等各种类型的空白,比[:blank:]包含的范围广
[:cntrl:]   #不可打印的控制字符(退格、删除、警铃...)
[:digit:]   #十进制数字
[:xdigit:]  #十六进制数字
[:graph:]   #可打印的非空白字符
[:print:]   #可打印字符
[:punct:]   #标点符号

\w          #匹配单词构成部分,等价于[_[:alnum:]]
\W          #匹配非单词构成部分,等价于[^_[:alnum:]]
\S          #匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\s          #匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。

注意:Unicode 正则表达式会匹配全角空格符
在使用正则表达式的时候最好加上引号避免出现问题
中括号'[ ]'中的内容无需进行转义比如说我们想匹配‘.’直接写[.]即可无需写成[\.],写了转义符反而会出错
中括号中的^表示非,中括号外的^表示行首

除了中括号内的特殊字符无需转义,别的情况下都需要进行转义

匹配次数

*           #匹配前面的字符任意次,包括0次,贪婪模式:尽可能长的匹配
.*          #任意长度的任意字符
\?          #匹配其前面的字符出现0次或1次,即:可有可无
\+          #匹配其前面的字符出现最少1次,即:肯定有且 >=1 次
\{n\}       #匹配前面的字符n次
\{m,n\}     #匹配前面的字符至少m次,至多n次
\{,n\}      #匹配前面的字符至多n次,<=n
\{n,\}      #匹配前面的字符至少n次

位置锚定

^               #行首锚定, 用于模式的最左侧
$               #行尾锚定,用于模式的最右侧
^PATTERN$       #用于模式匹配整行
^$              #空行,行首与行尾直接没有字符为空行
^[[:space:]]*$  #空白行,行首与行尾之间有空格、tab等一些不显示的非空字符
\< 或 \b         #词首锚定,用于单词模式的左侧
\> 或 \b         #词尾锚定,用于单词模式的右侧
\<PATTERN\>     #匹配整个单词
连续的字母,下划线,数字构成一个单词
别的符号(-、:、空格等)都算是分界符,分隔两个单词

分组其它

分组

分组:() 将多个字符捆绑在一起,当作一个整体处理,如:\(root\)+

后向引用:分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为: \1, \2, \3, ...
        \1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符

或者

或者:\|
#过滤1或者2abd
[root@localhost ~]#echo 1abc | grep "1\|2abd"
1abc

[root@localhost ~]#echo 2abc | grep "1\|2abd"

[root@localhost ~]#echo 2abd | grep "1\|2abd"
2abd

#过滤1abd或者2abd
[root@localhost ~]#echo 1abc | grep "\(1\|2\)abd"

[root@localhost ~]#echo 1abd | grep "\(1\|2\)abd"
1abd

练习:

1、显示/proc/meminfo文件中以大小s开头的行(要求:使用两种方法)
2、显示/etc/passwd文件中不以/bin/bash结尾的行
3、显示用户rpc默认的shell程序
4、找出/etc/passwd中的两位或三位数
5、显示CentOS7的/etc/grub2.cfg文件中,至少以一个空白字符开头的且后面有非空白字符的行
6、找出“netstat -tan”命令结果中以LISTEN后跟任意多个空白字符结尾的行
7、显示CentOS7上所有UID小于1000以内的用户名和UID
8、添加用户bash、testbash、basher、sh、nologin(其shell为/sbin/nologin),找出/etc/passwd用户名和shell同名的行
9、利用df和grep,取出磁盘各分区利用率,并从大到小排序

扩展正则表达式

前提需要命令支持扩展正则表达式

字符匹配

. 任意单个字符
[wang] 指定范围的字符
[^wang] 不在指定范围的字符

[:alnum:] 字母和数字
[:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z
[:lower:] 小写字母,示例:[[:lower:]],相当于[a-z]
[:upper:] 大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
[:digit:] 十进制数字
[:xdigit:]十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 标点符号

次数匹配

*               #匹配前面字符任意次
?               #0或1次
+               #1次或多次
{n}             #匹配n次
{m,n}           #至少m,至多n次

位置锚定

^               #行首
$               #行尾
\<, \b          #词首
\>, \b          #词尾

分组其它

()                  #分组
        后向引用:\1, \2, ...

| 或者
        a|b         #a或b
        C|cat       #C或cat
        (C|c)at     #Cat或cat

练习:

1、显示三个用户root、mage、wang的UID和默认shell
2、找出/etc/rc.d/init.d/functions文件中行首为某单词(包括下划线)后面跟一个小括号的行
3、使用egrep取出/etc/rc.d/init.d/functions中其基名
4、使用egrep取出上面路径的目录名
5、统计last命令中以root登录的每个主机IP地址登录次数
6、利用扩展正则表达式分别表示0-9、10-99、100-199、200-249、250-255
7、显示ifconfig命令结果中所有IPv4地址
8、将此字符串:welcome to magedu linux 中的每个字符去重并排序,重复次数多的排到前面

基本正则表达式与扩展正则表达式

基本正则表达式(BRE)和扩展正则表达式(ERE)的区别仅仅是元字符(meta charactor)的区别而已。

  • 基本正则表达式BRE:只有^$.[]* 是元字符
  • 拓展正则表达式ERE:^$.[]*+(){}?|都是元字符

ERE中新加的字符在BRE里只是普通的字符,如+ 只能匹配字符加号。如果想在BRE里使用特殊含义,需要转义。

#基本正则表达式
[root@localhost ~]#echo asdbasd | grep "a.+d"
[root@localhost ~]#echo asdbasd | grep "a.\+d"
asdbasd

#拓展正则表达式
[root@localhost ~]#echo asdbasd | grep -E "a.+d"
asdbasd

省去了书写大量“\”的烦恼

生产实例

#获取ip地址
ip  address show ens33 | grep inet | grep -o "\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}" | head -1