1.什么是正则表达式
又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
正则可以结合sed,vim,grep,awk等结合使用。
2.说一下简单用法
这里就使用grep来学习正则表达式
怎样利用正则表达式去"匹配位置"或者"匹配连续次数"?
2.1 因为grep默认是匹配行,当我们去选择进去"hello"进行筛选,他就默认会被与"hello"相关的行全部都例出来了
使用"^“用官方的意思来说在正则中锚定行首,”^"符号,他的意思是匹配以"hello"开头的行
[root@bogon ~]# cat test.txt
hello world
hi hello
hello,ls
[root@bogon ~]# grep "hello" test.txt
hello world
hi hello
hello,ls
[root@bogon ~]# grep "^hello" test.txt
hello world
hello,ls
使用"$"用官方的意思来说在正则中锚定行尾,用大白话来讲就是匹配以"hello"的行尾
可以看到匹配的第二行内容,也就是以"hello"结尾的内容
[root@bogon ~]# grep "hello$" test.txt
hi hello
我们知道了"^“和”$"分别是锚定行首和锚定行尾的意思,那如果结合使用会怎么样呢?
可以看到只是匹配到了第一行,因为只有第四行满足了条件,"hello"即在行首也在行尾
[root@bogon ~]# cat test.txt
hello world
hi hello
hello,ls
hello
[root@bogon ~]# grep "^hello$" test.txt
hello
匹配空行怎么匹配呢?
[root@bogon ~]# cat test.txt
hello world
hi hello
hello,ls
hello
[root@bogon ~]# grep "^$" test.txt
2.2
在这种情况下,怎么匹配到以hello单词开头或者结尾的行?
[root@bogon ~]# cat test1.txt
abchello world
abc helloabc abc
abc abchelloabc abc
可能看结果就看懂了"<"表示以hello作为词首的行
“>"表示以hello作为词尾的行
[root@bogon ~]# grep "\<hello" test1.txt
abc helloabc abc
[root@bogon ~]# grep "hello\>" test1.txt
abchello world
结合使用会怎么样?
用两种符号的结合的意思就是说,hello在即是行首又是行尾的情况下才会匹配到,通俗的意思就是说,只有在hello作为独立单词的时候才会被匹配到
[root@bogon ~]# cat test.txt
hello world
hi hello
hello,ls
hello
[root@bogon ~]# grep "\<hello\>" test.txt
hello world
hi hello
hello,ls
hello
当然如果觉得这两种符号不好用的话,也可以使用"\b"
[root@bogon ~]# grep "\bhello\b" test.txt
hello world
hi hello
hello,ls
hello
2.3
\B \b和\B的意思恰恰相反,\b是用来匹配"单词边界"的,也就是行首或者行尾
而\B则匹配非单词边界
我们会发现\b匹配词首 \B则恰好相反
[root@bogon ~]# cat test1.txt
abchello world
abc helloabc abc
abc abchelloabc abc
[root@bogon ~]# grep "\Bhello" test1.txt
abchello world
abc abchelloabc abc
注意测试文件不一样,但是从匹配到的字符可以看出来结果
[root@bogon ~]# grep "\<hello\>" test.txt
hello world
hi hello
hello,ls
hello
[root@bogon ~]# grep "\Bhello\B" test1.txt
abc abchelloabc abc
2.4 小结
^:表示锚定行首,此字符后面的任意内容必须出现在行首,才能匹配。
$:表示锚定行尾,此字符前面的任意内容必须出现在行尾,才能匹配。
^$:表示匹配空行,这里所描述的空行表示"回车",而"空格"或"tab"等都不能算作此处所描述的空行。
^abc$:表示abc独占一行时,会被匹配到。
<或者\b :匹配单词边界,表示锚定词首,其后面的字符必须作为单词首部出现。
>或者\b :匹配单词边界,表示锚定词尾,其前面的字符必须作为单词尾部出现。
\B:匹配非单词边界,与\b正好相反。
**
3.正则表达式的常用符号
**
3.1
"."代表匹配任意单个字符,也可以理解为替换单个字符
"."可以代替字母 符号或者数字都是可以的
3.2
[[:alpha:]] 表示"任意字母"(不区分大小写)
在默认情况下只匹配两个任意字母
"[[:alpha:]]\{4\}"表示4个连续的任意字母
结合这个命令grep “a[[:alpha:]]\{4\}” test3.txt,意思就是说匹配a之后的4个任意字母
如何区分大小写
[[:alpha:]]上面已经说过了,这种匹配是不会区分大小写的
[[:upper:]] 表示任意大写字母
[[:lower:]] 表示任意小写字母
可以发现无论是[[:upper:]]或者[[:lower:]] 匹配的都是为"A"或“a”之后的内容为大小写
3.3 小结
我们替换"[[: :]]"中的单词,即可表示不同的含义。
那么我们来看看一些常用的符号都表示什么含义。
[[:alpha:]] 表示任意大小写字母
[[:lower:]] 表示任意小写字母
[[:upper:]] 表示任意大写字母
[[:digit:]] 表示0到9之间的任意单个数字(包括0和9)
[[:alnum:]] 表示任意数字或字母
[[:space:]] 表示任意空白字符,包括"空格"、"tab键"等。
[[:punct:]] 表示任意标点符号
3.4 花括号作用
3.4.1
"[ ]"表示匹配指定范围内的任意单个字符
"[]"与[[:alpha:]]是等价的,意思就是说“[[:alpha:]]“代表的是任意字符而“[]”则表示可以指定任意字符
如图所示:
匹配从a-z的所有字符与[[:lower:]]是等效的。
匹配从A-Z的所有字符与[[:upper:]]是等效的。
如果想区分大小写全部匹配怎么做?
“[a-Z]” 即可表示不区分大小写与"[a-zA-Z]"等效
3.4.2
如果是数字应该如何表示
[0-9]与[[:digit:]]等效,都表示0到9之间的任意单个数字
试一下只筛选出"a123"的行吧
grep “^a[0-9]\{3\}” test6.txt
解释 :
^a表示以a开头的行
[0-9]表示 a后面的内容为0-9的任意数字
\{3\} 表示匹配除去a后面为3个字符
3.4.3
"[]"代替任意字符其实也有点or的意思,条件满足其中一个即可
例如
表示以小写c开头后面的字符可以是3或者大写C或者#进行匹配
3.4.4 取反筛选
取反的意思可以理解为除去指定内容之外的其他内容
需要注意的是[]里的"^“作用是不一样的,”[]“里面的”^“表示是取反
那如果取反[^0-9]会怎么样呢?
没错,除了数字的内容都匹配到了
3.4.5 小结
同理:
[^a-z]表示非小写字母的单个字符可以被匹配到。
[^A-Z]表示非大写字母的单个字符可以被匹配到。
[^a-zA-Z]表示非字母的单个字符可以被匹配到,比如数字或符号。
[^a-zA-Z0-9]表示非字母、非数字的单个字符可以被匹配到,比如符号。
结合之前的理论,你一定想到了,既然[0-9]与[[:digit:]]等效,那么[^0-9]与[^[:digit:]]等效吗?
试试就知道了,如下图所示,的确是等效的。
举一反三
[^0-9]与[^[:digit:]]等效
[^a-z]与[^[:lower:]]等效
[^A-Z]与[^[:upper:]]等效
[^a-zA-Z]与[^[:alpha:]]等效
[^a-zA-Z0-9]与[^[:alnum:]]等效
其实,不仅[0-9]与[[:digit:]]能够表示数字,还有一些简写格式的符号也能表示数字,比如"\d,但是,并不是所有的正则表达式处理器都能够识别这些简写格式
是无法识别\d这种简短格式,之所以能匹配到,可以是因为"\"理解为了转义字符
如果想让他识别就需要使用-P选项,表示grep使用兼容perl的正则表达式引擎
\d 表示任意单个0到9的数字
\D 表示任意单个非数字字符
\t 表示匹配单个横向制表符(相当于一个tab键)
\s表示匹配单个空白字符,包括"空格","tab制表符"等。
\S表示匹配单个非空白字符
3.0总结
. 表示匹配任意单个字符
* 表示匹配前面的字符任意次,包括0次
[ ] 表示匹配指定范围内的任意单个字符
[^ ] 表示匹配指定范围外的任意单个字符
[[:alpha:]] 表示任意大小写字母
[[:lower:]] 表示任意小写字母
[[:upper:]] 表示任意大写字母
[[:digit:]] 表示0到9之间的任意单个数字(包括0和9)
[[:alnum:]] 表示任意数字或字母
[[:space:]] 表示任意空白字符,包括"空格"、"tab键"等。
[[:punct:]] 表示任意标点符号
[0-9]与[[:digit:]]等效
[a-z]与[[:lower:]]等效
[A-Z]与[[:upper:]]等效
[a-zA-Z]与[[:alpha:]]等效
[a-zA-Z0-9]与[[:alnum:]]等效
[^0-9]与[^[:digit:]]等效
[^a-z]与[^[:lower:]]等效
[^A-Z]与[^[:upper:]]等效
[^a-zA-Z]与[^[:alpha:]]等效
[^a-zA-Z0-9]与[^[:alnum:]]等效
#简短格式并非所有正则表达式解析器都可以识别
\d 表示任意单个0到9的数字
\D 表示任意单个非数字字符
\t 表示匹配单个横向制表符(相当于一个tab键)
\s表示匹配单个空白字符,包括"空格","tab制表符"等
\S表示匹配单个非空白字符
4.正则表达式:分组
不知道怎么解释,直接开始试验吧,一式便知
问题来了,这里用到"连续次数匹配",不论是"hello{2}“还是"hello{3}这里匹配的始终是字符串前面的单个字符,也就是字母"o”。
4.1
那应该怎么办呢?
这里就需要用到分组,对字符串进行拆分,分组。
"\( \)"就表示分组。表示将其中的内容看做一个分组,看做一个整体。那么其实匹配的也就是hello
"\(hello\)\{2\}“这个正则表达式就表示hello字符串连续出现两次,也就是"hellohello”
如果我想只找到"helloobc"的字符串应该怎么样呢?还是比较容易理解的 "\(hello\)“可以理解为一个组,”\(obc\)“理解为一个组
4.2
分组嵌套
结果是怎么得出来的呢?
."\(ab\(cd\)\{2\}\)"
将ab和cd进行分组操作整合成一个整体也就是"abcd"在连续匹配两侧"cd"也就是"abcdcd",那为什么会匹配都匹配到了呢,原因是默认grep是全部匹配的。如果我们指定一下以什么开头的,或只匹配结尾会怎么样呢?
这时候我们会发现其实只匹配了一次,只是因为grep的机制导致的全部都匹配到了,所以完整命令应该是"\(ab\(cd\)\{2\}\)\{2\}"
进行重复查找两次,这就是分组的嵌套
5.正则表达式之后向引用
注意向后引用是以分组为前提的
5.1 先来个开胃菜
可能看着有点难以理解但是其实还是比较简单的
##-o 显示被模式匹配到的字符串。
^a表示以a开头的行,"."代表任意字符,\{2\}表示匹配任意字符两次,也就是a后面的两个字符,这样就得到abc了
5.2进入正题
问题来了,这样的文本怎么查看?
字符不同,字符数量也不一致
这时候就用到了向后引用…
很明显第一次尝试失败了,因为要引用字符串进行匹配
那应该怎么做呢?
我们可以看到第一行和第一行的第一个字段和第三个字段都匹配,而第一个字段和第三个字段就不匹配
看下测试效果
"\1"表示整个正则中第1个分组中的正则所匹配到的结果,这样说可能不容易理解,我们用大白话说一遍。
在上例中,整个正则中只出现了1个分组,就是"\(H.\{4\}\)",当它与示例文件中的第一行文本进行匹配时,会匹配到Hello字符串,这时,"\1"就表示Hello字符串。
当正则"\(H.\{4\}\)“与示例文件中的第二行文本进行匹配时,会匹配到Hiiii字符串,这时,”\1"就表示Hiiii字符串。
也就是说,"\1"必须与整个正则中第1个分组中的正则(也就是红色部分的正则)所匹配到的结果相同。
换句话说就是,"\1"引用了整个正则中第1个分组中的正则(也就是红色部分的正则)所匹配到的结果。
你知道为什么必须为"H.\{4\}"添加分组了吗?因为,当我们为"H.\{4\}"添加了分组以后,"H.\{4\}"就变成了整个正则中第1个分组中的正则,当"H.\{4\}“匹配到的结果为Hello时,”\1"就引用了Hello,当"H.\{4\}“匹配到的结果为Hiiii时,”\1"就引用了Hiiii。
练习拓展一下
练习1
练习二
怎么样经过上面的实践,其实一眼就能看懂了我们首先将“\(^a.\{1\}\) ”分为一个组,将“\(\b.\{1\}\) ”分为一个组,通过向后引用,匹配到组一匹配字段三的内容,组二匹配字段4的内容
由于红色分组的左侧部分排在最前面,所以红色分组是整个正则中的第1个分组。
由于蓝色分组的左侧部分排在第2位,所以蓝色分组是整个正则中的第2个分组。
注意:排序时也仅仅按照分组符号的左侧部分排序,分组符号的右侧部分不算在排序范围内。
5.3小结
不管分多少个组,向后引用都可以以此累加,代替字段内容内容
\( \) 表示分组,我们可以将其中的内容当做一个整体,分组可以嵌套。
\(ab\) 表示将ab当做一个整体去处理。
\1 表示引用整个表达式中第1个分组中的正则匹配到的结果。
\2 表示引用整个表达式中第2个分组中的正则匹配到的结果。
6. 转义符
转义符笔者理解的意思就是说将特殊有意义的符号,转化为普通符号(也就是不做任何运算,显示出来即可)。
6.1
例如
默认的".“符号代表的是代替任意单个字符,那如果我只想匹配到a…的内容,应该怎么去做呢?
使用转义字符,将”.“只作为”."来使用,不做其他任何意义
6.2
需要注意的是,在我们学习过的基本正则表达式当中"\b","\?",又或者"\+",我们想让他作为普通字符的时候应该怎么做?
不用想的那么复杂,不使用“\”即可
同理匹配\反斜杠本身,需要在反斜杠前面加转义符比如
如果加入双引号则会报错
因此如果要匹配可以这样匹配
7. 基础正则表达式总结
7.1
#################常用符号#################
. 表示任意单个字符。
/* 表示前面的字符连续出现任意次,包括0次。
.* 表示任意长度的任意字符,与通配符中的*的意思相同。
\ 表示转义符,当与正则表达式中的符号结合时表示符号本身。
[ ]表示匹配指定范围内的任意单个字符。
[^ ]表示匹配指定范围外的任意单个字符。
#################单个字符匹配相关#################
[[:alpha:]] 表示任意大小写字母。
[[:lower:]] 表示任意小写字母。
[[:upper:]] 表示任意大写字母。
[[:digit:]] 表示0到9之间的任意单个数字(包括0和9)。
[[:alnum:]] 表示任意数字或字母。
[[:space:]] 表示任意空白字符,包括"空格"、“tab键"等。
[[:punct:]] 表示任意标点符号。
[^[:alpha:]] 表示单个非字母字符。
[^[:lower:]] 表示单个非小写字母字符。
[^[:upper:]] 表示单个非大写字母字符。
[^[:digit:]] 表示单个非数字字符。
[^[:alnum:]] 表示单个非数字非字母字符。
[^[:space:]] 表示单个非空白字符。
[^[:punct:]] 表示单个非标点符号字符。
[0-9]与[[:digit:]]等效。
[a-z]与[[:lower:]]等效。
[A-Z]与[[:upper:]]等效。
[a-zA-Z]与[[:alpha:]]等效。
[a-zA-Z0-9]与[[:alnum:]]等效。
[^0-9]与[^[:digit:]]等效。
[^a-z]与[^[:lower:]]等效。
[^A-Z]与[^[:upper:]]等效
[^a-zA-Z]与[^[:alpha:]]等效
[^a-zA-Z0-9]与[^[:alnum:]]等效
#简短格式并非所有正则表达式解析器都可以识别。
\d 表示任意单个0到9的数字。
\D 表示任意单个非数字字符。
\t 表示匹配单个横向制表符(相当于一个tab键)。
\s表示匹配单个空白字符,包括"空格”,"tab制表符"等。
\S表示匹配单个非空白字符。
#################次数匹配相关#################
? 表示匹配其前面的字符0或1次
+ 表示匹配其前面的字符至少1次,或者连续多次,连续次数上不封顶。
{n} 表示前面的字符连续出现n次,将会被匹配到。
{x,y} 表示之前的字符至少连续出现x次,最多连续出现y次,都能被匹配到,换句话说,只要之前的字符连续出现的次数在x与y之间,即可被匹配到。
{,n} 表示之前的字符连续出现至多n次,最少0次,都会陪匹配到。
{n,}表示之前的字符连续出现至少n次,才会被匹配到。
#################位置边界匹配相关#################
^:表示锚定行首,此字符后面的任意内容必须出现在行首,才能匹配。
$:表示锚定行尾,此字符前面的任意内容必须出现在行尾,才能匹配。
^$:表示匹配空行,这里所描述的空行表示"回车",而"空格"或"tab"等都不能算作此处所描述的空行。
^abc$:表示abc独占一行时,会被匹配到。
<或者\b :匹配单词边界,表示锚定词首,其后面的字符必须作为单词首部出现。
>或者\b :匹配单词边界,表示锚定词尾,其前面的字符必须作为单词尾部出现。
\B:匹配非单词边界,与\b正好相反。
#################分组与后向引用#################
\( \) 表示分组,我们可以将其中的内容当做一个整体,分组可以嵌套。
\(ab\) 表示将ab当做一个整体去处理。
\1 表示引用整个表达式中第1个分组中的正则匹配到的结果。
\2 表示引用整个表达式中第2个分组中的正则匹配到的结果。
7.2 那么我们学习了这么多正则表达式的语法,现在能做什么呢?
1.那么,如果我们想要从ifconfig命令的结果中找出IPV4格式的IP地址,应该怎么办呢?
在写所有查询过滤多个字符串的时候,我们应该这知道这些字符串的共同点应该是什么?在进行过滤
过滤出192.168网段的ip
过滤出网卡名称
过滤出IP
##两种方法结果虽然一样,但是取值是不一样的
过滤手机号
##实现问题的方法千变万化 一定要学会灵活运用
8.扩展正则表达式
正则表达式可以分为"基本正则表达式"和"扩展正则表达式"。上面的所有语法都是"基本正则表达式",无"基本正则表达式"和"扩展正则表达式"论是这些通用的符号所表达的意思都是相同的。
我们提到过,grep命令默认只支持基本正则表达式,如果想要让grep命令能够支持扩展的正则表达式,则需要使用"-E"选项,说白了也就是egrep,在上文中也说过-E选项的作用也就是支持了epel引擎。
在基本正则表达式中,{n} 表示前面的字符连续出现n次,将会被匹配到。
在扩展正则表达式中,{n} 表示前面的字符连续出现n次,将会被匹配到。
在基本正则表达式中,( ) 表示分组,(ab) 表示将ab当做一个整体去处理。
在扩展正则表达式中,( ) 表示分组,(ab) 表示将ab当做一个整体去处理。
在扩展正则表达式中:
( ) 表示分组
(ab) 表示将ab当做一个整体去处理。
\1 表示引用整个表达式中第1个分组中的正则匹配到的结果。
\2 表示引用整个表达式中第2个分组中的正则匹配到的结果。
? 表示匹配其前面的字符0或1次
- 表示匹配其前面的字符至少1次,或者连续多次,连续次数上不封顶。
{n} 表示前面的字符连续出现n次,将会被匹配到。
{x,y} 表示之前的字符至少连续出现x次,最多连续出现y次,都能被匹配到,换句话说,只要之前的字符连续出现的次数在x与y之间,即可被匹配到。
{,n} 表示之前的字符连续出现至多n次,最少0次,都会陪匹配到。
{n,}表示之前的字符连续出现至少n次,才会被匹配到。
扩展正则表达式中,还有一个常用的符号,是基本正则表达式中所没有的,它就是"|",他有点或者的意思,当我们给出多条件的时候,只需要满足其中一个或者满足多个。
下面将"(com|net)"进行了分组也就是将他看成了一个整体。
那如果我们过滤出邮箱怎么怎么做呢?
首先我们应该知道邮箱格式是怎么样的
比如使用最多的163邮箱
用户名@163.com
1.用户名长度
2.@之后的固定格式,长度
3.后缀
看似负责其实还是特别简单的,我们对他进行拆分,与之前的邮箱格式进行对应。
总结
常用符号
. 表示任意单个字符。
* 表示前面的字符连续出现任意次,包括0次。
.* 表示任意长度的任意字符,与通配符中的*的意思相同。
\ 表示转义符,当与正则表达式中的符号结合时表示符号本身。
| 表示"或者"之意
[ ]表示匹配指定范围内的任意单个字符。
[^ ]表示匹配指定范围外的任意单个字符。
单个字符匹配相关
[[:alpha:]] 表示任意大小写字母。
[[:lower:]] 表示任意小写字母。
[[:upper:]] 表示任意大写字母。
[[:digit:]] 表示0到9之间的任意单个数字(包括0和9)。
[[:alnum:]] 表示任意数字或字母。
[[:space:]] 表示任意空白字符,包括"空格"、"tab键"等。
[[:punct:]] 表示任意标点符号。
[^[:alpha:]] 表示单个非字母字符。
[^[:lower:]] 表示单个非小写字母字符。
[^[:upper:]] 表示单个非大写字母字符。
[^[:digit:]] 表示单个非数字字符。
[^[:alnum:]] 表示单个非数字非字母字符。
[^[:space:]] 表示单个非空白字符。
[^[:punct:]] 表示单个非标点符号字符。
[0-9]与[[:digit:]]等效。
[a-z]与[[:lower:]]等效。
[A-Z]与[[:upper:]]等效。
[a-zA-Z]与[[:alpha:]]等效。
[a-zA-Z0-9]与[[:alnum:]]等效。
[^0-9]与[^[:digit:]]等效。
[^a-z]与[^[:lower:]]等效。
[^A-Z]与[^[:upper:]]等效
[^a-zA-Z]与[^[:alpha:]]等效
[^a-zA-Z0-9]与[^[:alnum:]]等效
次数匹配相关
? 表示匹配其前面的字符0或1次
+ 表示匹配其前面的字符至少1次,或者连续多次,连续次数上不封顶。
{n} 表示前面的字符连续出现n次,将会被匹配到。
{x,y} 表示之前的字符至少连续出现x次,最多连续出现y次,都能被匹配到,换句话说,只要之前的字符连续出现的次数在x与y之间,即可被匹配到。
{,n} 表示之前的字符连续出现至多n次,最少0次,都会陪匹配到。
{n,}表示之前的字符连续出现至少n次,才会被匹配到。
位置边界匹配相关
^:表示锚定行首,此字符后面的任意内容必须出现在行首,才能匹配。
$:表示锚定行尾,此字符前面的任意内容必须出现在行尾,才能匹配。
^$:表示匹配空行,这里所描述的空行表示"回车",而"空格"或"tab"等都不能算作此处所描述的空行。
^abc$:表示abc独占一行时,会被匹配到。
\<或者\b :匹配单词边界,表示锚定词首,其后面的字符必须作为单词首部出现。
\>或者\b :匹配单词边界,表示锚定词尾,其前面的字符必须作为单词尾部出现。
\B:匹配非单词边界,与\b正好相反。
分组与后向引用
( ) 表示分组,我们可以将其中的内容当做一个整体,分组可以嵌套。
(ab) 表示将ab当做一个整体去处理。
\1 表示引用整个表达式中第1个分组中的正则匹配到的结果。
\2 表示引用整个表达式中第2个分组中的正则匹配到的结果。
正则已经学完了,是不是感觉很简单呢!!