正则表达式
正则表达式是用来提取数据的
学习正则表达式的方法是:熟能生巧,能够独立写出正则表达式,对于一个问题可以写出多种正则表达式。并且能够结合sed,awd,grep三剑客解决常见的问题。
正则表达式的应用非常广泛,很多的编程语言都支持正则表达式,用于处理字符串提取数据。比如:python,java,golang,js等编程语言都支持正则表达式。
为什么要使用正则表达式?
正则表达式,数据处理的人去使用,数据分析的,爬虫工程师前后端开发,对各种数据提取,构造
运维人员提取文件数据的关键信息,做分析,日志分析,提取网站的链接等操作需要使用到正则表达式。
正则表达式的语法
关于字符集的设置
你会发现有很多的Shell脚本里面都有这样一个语句
LC_ALL=C
vim /etc/init.d/network打开这个文件可以看到LC_ALL
这个变量赋值的动作,是等于还原linux系统的字符集,因为我们的系统本身是支持多语言的,比如:德文,英文,中文等。每一种语言都有其特有的语言,字符,计算机为了统一字符,生成了编码表。
平时我们都喜欢将linux支持中文,这样导致系统的编码是中文,很可能会导致我们的正则表达式出现错误,所以需要还原系统的编码。
LANG='zh-CN'
所以需要执行一个还原本地所有编码信息的变量: LC_ALL=C
将当前的操作系统的编码还原成为系统初始化的编码
作用就是修改linux的字符集,通过locale命令可以查看到本地的字符集设置,linux可以通过如下变量设置程序运行的不同语言环境,比如中文、英文环境。
想要设置成为中文:export LC_ALL='zh_CN.UTF-8'
尝试i执行ls --help这个时候这个命令的帮助文档就变成了中文的了,但是这样只是方便了你自己看,并没有方便程序,所以还是建议将这个LC_ALL还原成为系统默认的字符集
export LC_ALL=C
通配符和正则表达式的区别
从语法上记住,只有awk,grep,sed才识别正则表达式的符号,其他的都是通配符
只有使用这三个命令的操作,写的才是特殊符号,才是正则表达式--提取数据流的关键信息
其他的linux命令的操作,都是通配符的概念,以及---查找文件名
正则表达式的分类
基于UNIX标准下的正则表达式符号规则有两类:
POSIX基础正则表达式引擎,这个是早期unix系统中就已经存在的一些符号
POSIX扩展正则表达式引擎又额外的出现了一堆特殊字符,这个叫做扩展正则表达式
基本正则表达式与扩展正则
^ $ . [ ] * 这些称为元字符
基础正则表达式的英文名是BRE
扩展正则表达式的英文名式ERE
扩展正则表达式在基本正则表达式的基础上面增加了
() {} ? + | 等等元字符
为什么要讲解基本正则表达式和扩展正则呢?
因为grep
awk sed 这三个命令在处理正则的时候,默认的也只是认识基本正则表达式
如果写了分组,或者{}等扩展正则的符号,必须要给grep,这些命令加上额外的参数
让这些命令能够识别这些扩展正则。
学习正则表达式
首先准备一些测试的数据
I am person alice,
I os linux,windows,macos
I like zhognwen
My vb is http://alice.cn
Our balabal site is https://xxx.com
My qq num is 2635768337
Good good day, up pup upu !
my name is wu moum mou.
这里使用的时候如果没有使用变量就建议使用单引号
现在使用一条命令:grep '^m' t1.log
从t1.log这个文件中找到以m开头的行,前面的内容已经写入到这个文件中
这里只找到了m这个字符
加上-n选项可以指定grep的结果出现这个行的行号
加上-o选项可以只显示筛选到的内容
练习grep尖角号
找到以M开头的行
找到以m开头的行
找到m或者M开头的行
只显示grep每次匹配到的结果,而不是匹配到的文本行数据:
找出以my开头的行
匹配出qq的那一行
匹配行内容,且显示行号:
找出包含i字符的行
找出以I开头的行
找出以I开头的行,并且只显示匹配内容
美元符号
美元符号$
匹配所有以字符n结尾的行
匹配以所有.结尾的行
注意点不能匹配换行符号
单引号和双引号的区别
单引号双引号的区别:
单引号,所见即所得,可以用于匹配如标点符号,还原其本义
双引号能够识别linux的特殊符号,或者变量,需要借助转义符号还原字符本义
当需要引号嵌套的时候一般的做法是双引号,嵌套单引号
尖角号,美元符号匹配空行
^符号匹配以这个字符开头的行
$符号匹配以这个字符结尾的行
^$匹配以空开头,空结尾的空行
点符号
注意点符号可以匹配空格和任何的字符,但是不能匹配换行符号,所以拿不到空行。
grep -n '.' -o t.log通过这个命令可以验证这个结论
在点前面加上一个字符加深理解:
练习:
匹配某ac的行
点美元符号
可以拿到每一行结尾的符号
.表示除了换行符号的任意一个字符
$表示以这个字符结尾
.$就是表示每一行结尾的符号
点和转义
拿到每一行结尾的普通小数点
网址:测试正则表达式的
正则表达式在线测试 | 菜鸟工具 (jyshare.com)
比如这里匹配一个换行符号
单词边界,换行符,制表符
\b是匹配单词边界
\n匹配的是换行符号,表示向下移动一行,不会左右移动
\r表示匹配回车符,表示return,上面的换行表示newline,
\r表示返回到当前行的最左边
在windows和linux对于换行符号是有区分的
在linux中,换行符号就是\n
在windows中,换行符号是\r\n
这个是在开发的时候需要注意的
\t表示一个制表符,相当于四个空格键
星星
表示重复前面这个符号的零次或者多次
没有这个符号的行也会打印出来,这里我更改了一下测试数据
点星
点是匹配任意一个字符,星是重复前面一个字符0次或者多次
所以最后的结果是有没有东西全部找到,所以这里能够找到不包括空行的和包括空行的所有内容
.*的应用
需要注意的是因为.的存在会忽略换行符号
i love you
i hate you
love.*hate这样的正则是不可以使用的,拿不到数据,
这个在爬虫的时候需要注意
尖点星
以任意内容开头
找到以i开头的行,不区分大小写的
找到任意以i开头,并且匹配到后续所有数据,不区分大小写
找出任意以字母i开头的行,并且以h结尾的行
这里我又修改了一下测试数据
点星美元
以任意多个元素结尾的行
这个的结果就是.*的结果
从开始拿到结尾
最后的基本正则
匹配所有小写单个字母
匹配所有的大写单个字母
匹配小写字母和数字
匹配大写字母和数字
匹配大写小写字母数字无空格特殊符号
匹配特殊符号
扩展正则
说明:
前面使用grep都是没有加参数的使用的都是基本正则表达式
现在grep需要使用-E选项,这样grep就可以使用基本正则表达式了
以前是使用egrep,这里不推荐使用,只使用grep -E即可
此外还可以进行转义,但是这样会带来大量的转义符号,所以推荐使用E选项表示使用
扩展正则
花括号
这个表示重复t一次到三次
这里没有使用E选项
写上E选项更加清晰
匹配数字8一次到三次
每次最少找出2个8,最多3个8
每次只找到三个8
这里又更改了测试数据
重复至少n次
这个是至少重复1次
反之是最多重复多少次
加号
加号表示重复前面一个字符一次或者多次
注意这个和星的区别
找到连续的数字
这两个看起来是一样的但是加上o选项之后知道+是提取出来这些连续的数字
而没有+的是单个数字
找出所有的单词
问号
匹配一次或者零次
或者
找出空白行还有找出注释行
同时排除文件的空行还有注释行
这样使用就不会改变序号
查看内存和swap的容量信息
括号和分组符号
在括号里面也是可以写正则的
grep不好体现括号向后引用的用法,到sed的时候就可以体现向后引用的用法
基本正则练习
关于正则表达式,单个正则字符还认识,但是组合在一起就不认识了,为什么?
这个是因为对单个字符没有理解。
解决办法:编写思维导图,编写笔记,练习不看答案就能够写出这个正则表达式,并且能够对于一个问题编写多种正则。
测试数据:
I am teacher yuchao.
I teach linux,python.
testtttsss0001123566666
I like video,games,girls
#I like girls.
$my blog is http://yuchaoit.cn
#my blog is http://yuchaoit.cn/
#mysite is https://www.cnblogs.com/pyyu
My qq num is 877348180.
my phone num is 15210888008.
找出以什么开头的行
找出以i开头的行,忽略大小写
查找以什么结尾的行
查找以u结尾的行
找出以点结尾的行
尖美元符号^$以空开头以空结尾(提取出空白行,什么都没有)
找出以i开头s结尾的行
找出空白行
排除空行提取有用的信息行
转义符号
找出以$开头的行
匹配字符
匹配小写字母(下面这种方式是unix风格的)
找到以小数点或者s结尾的行
找出以i开头,结尾不是.的行,这里忽略大小写
扩展正则练习
准备数据
I am teacher yuchao.
I teach linux,python.
testtttsss000123566666
I like video,games,girls
#I like girls.
$my blog is http://www.yuchaoit.cn
#my site is https://www.cnblogs.com/pyyu
My qq num is 877348180.
my phone num is 15210888008.
匹配手机号
最简单的考虑是只有11位数字(但是这样并不靠谱)
\b \s这样的符号是在perl语言后来诞生的新兴正则表达式语法
这种东西并不是通用的东西,因为这些东西在某些地方能用,
在一些地方又不能使用
现在的基本正则和扩展正则,这种东西才是通用的
\b是匹配单词的边界
以一开头的11位数字(注意^是行首)
比较正确的方式
手机号码的规则如下:
第一位 1
第二位 3到9
第三位到第十一位 是数字
这个是结合了中国电信、联通、移动的手机号
匹配qq号(这里的w是显示全部符合的)
查找所有单词中出现字母连续的行,比如www,http重复,可以采用分组,向后引用的特性匹配(注意这里不要使用加号,因为加号可以匹配一次,也可以匹配多次,所以要想办法不要让他匹配一次)
如果只想要提取三个连续一样的字母呢?
提取服务器主机名
提取完整的连接地址(注意固定死的东西就不要正则了,直接些上去就行了,三级域名是可有可无的)
下面这种通用性更强