ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

linux正则表达式

2022-04-12 18:31:07  阅读:260  来源: 互联网

标签:字符 grep log 正则表达式 正则 linux 匹配


正则表达式预习

什么是正则表达式

正则表达式就是为了处理大量的字符串而定义的一套规则和方法
通过定义的这些特殊符号的辅助,系统管理员就可以快速过滤,替换或输出需要的字符串
Linux正则表达式一般以行为单位处理的

如何使用正则表达式

通常linux运维工作,都是面临大量带有字符串的内容,
如:
配置文件
程序代码
命令输出结果
日志文件

且此类字符串内容,我们常会有特定的需要,查找出符合工作需要的特定的字符串,因此正则表达式就出现了

正则表达式时一套规则和方法
正则工作时以单位进行,一次处理一行
正则表达式化繁为简,提高工作效率
linux仅受三剑客(sed,awk,grep)支持,其他命令无法使用

学习正则的注意事项

正则表达式应用非常广泛,很多编程语言都支持正则表达式,用于处理字符串提取数据
Linux下普通命令无法使用正则表达式的,只能使用linux下的三个命令,结合正则表达式处理
sed
grep
awk
通配符是大部分普通命令都支持的,用于查找文件或目录
而正则表达式时通过三剑客命令文件(数据流)中过滤内容的,注意区别
以及注意字符集,需要设置 LC_ALL=C ,注意这一点很重要

关于字符集设置

会发现很多shell脚本里都有这么一个语句如下

作用是修改linux的字符集,通过locale命令可以查看本地字符集设置

linux通过如下变量设置程序运行的不同语言环境,如中文,英文环境


[root@yuchao-tx-server ~]# locale
LANG=en_US.UTF-8
LC_CTYPE="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_PAPER="zh_CN.UTF-8"
LC_NAME="zh_CN.UTF-8"
LC_ADDRESS="zh_CN.UTF-8"
LC_TELEPHONE="zh_CN.UTF-8"
LC_MEASUREMENT="zh_CN.UTF-8"
LC_IDENTIFICATION="zh_CN.UTF-8"
LC_ALL=zh_CN.UTF-8
一般我们会使用 $LANG 变量来设置linux的字符集,一般设置为我们所在的地区,如 zh_CN.UTF-8

[root@bogon ~]# echo $LANG
en_US.UTF-8

为了让系统正确执行shell语句(由于自定义修改的不同语言环境,对一些特殊符号的处理区别,如中文输入法,英文输入法下的标点符号,导致shell无法执行)

我们会使用如下语句,恢复linux的所有的本地化设置,恢复系统到初始化的语言环境

[root@bogon ~]# export LC_ALL=C

通配符和正则的区别

从语法上就记住,只有awk,grep,sed才识别正则表达式符号,其他都是通配符
从用法上区分
表达式操作的是文件,目录名(属于是通配符)
表达式操作的是文件内容(正则表达式)

如下符号区别
通配符和正则表达式,都有 *  ?  [abcd]  符号
通配符中,都是用来标识任意的字符
如 ls  *.log  可以找到 a.log  b.log  ccc.log


正则中,都是用来表示这些符号前面的字符,出现的次数,
如: grep  'a*'



实际案例
通配符,一般用于对文件名的处理,查找文件
如ls命令结合 *
意思式匹配任意字符
[root@bogon test]# ls *.log
a.log  d.log  g.log    yc3.log  yu1.log  yu4.log       yuyu.log
b.log  e.log  yc1.log  yc4.log  yu2.log  yu5.log
c.log  f.log  yc2.log  yc5.log  yu3.log  yuchao01.log




而三剑客,结合*符号,是处理文件内容,如grep
此时的*作用就不一样了

正则表达式分类

使用正则表达式的问题是,有两大类正则表达式规范,linux不同的应用程序,会使用不同的正则表达式
例如
不同的编程语言使用正则(python,java)
linux实用工具(sed,awk,grep)
其他软件使用正则(mysql,nginx)

正则表达式是通过正则表达式引擎(regular expression engine)实现的,正则表达式引擎是一套底层软件,负责解释正则表达式模式并使用这些模式进行文本匹配

在linux中,有两种流行的正则表达式引擎

基于unix标准下的正则表达式符号规则有两类:
POSIX基础正则表达式(basic regular expression,BRE)引擎

POSIX扩展正则表达式(extended regular expression,ERE)引擎 

解释posix
POSIX(Portable Operating System Interface)是Unix系统的一个设计标准。
当年最早的Unix,源代码流传出去了,加上早期的Unix不够完善,于是之后出现了好些独立开发的与Unix基本兼容但又不完全兼容的OS,通称Unix-like OS

两类,正则表达式符号

linux规范将正则表达式分为了两种
基本正则表达式(BRE,basic,regular,expression)

BRE对应元字符有
^  $  .  []  *

其他符号式普通字符
;  \

扩展正则表达式(ERE、extended regular expression)
ERE在BRE基础上,增加了
()  {}  ?  +  |  等元字符

转义符
反斜杠  \
反斜杠用于在元字符前添加,使其成为普通字符

基本正则表达式(BRE)

测试文本数据

[root@bogon test]# cat chaoge666.txt 
I am teacher yuchao.
I teach linux,python!

I like english

My website is http://yuchaoit.cn
Our school site is https://apecome.com
My qq num is 877348180

Good good study , day day up!





关于单引号、双引号

正则的模式,建议使用双引号
如果为涉及变量等,用单引号也不影响

grep与正则

NAME
       grep, egrep, fgrep - print lines matching a pattern

SYNOPSIS
       grep [OPTIONS] PATTERN [FILE...]
       grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]
       
       
例如传入的pattern(模式是),我们可以统称你写的正则是模式
^m , 以m开头的行
[root@bogon test]# grep -i -n '^m' chaoge666.txt 
6:My website is http://yuchaoit.cn
8:My qq num is 877348180

^ 尖角符

语法
写于最左侧,如
^yu 逐行匹配,找到以yu开头的内容

结合grep用法,-i 忽略大小写

结合grep的参数 -o 只显示一行中匹配出来的内容

结合grep,过滤出以i开头的行,且显示行号

$ 美元符

语法

word$ 匹配以word结尾的行

匹配所有以字符n结尾的行

匹配所有以小数点 . 结尾的行,这里因为 . 也有特殊作用,因此得使用单引号,或者转义符

单、双引号区别

单引号,所见即所得,可以用于匹配如标点符号,还原其本义

双引号,能够识别linux得特殊符号,或变量,需要借助转义还原字符本义

当需要引号镶套时,一般做法是,双引号,镶套单引号

^$ 匹配空行

找出文件的空行

. 点符

.  匹配除了换行符以外所有得内容,字符+空格 ,除了换行符

.  点处理空格,换行

.  可以匹配到空格,以及任意字符

. 匹配除换行符得所有字符

. 代表任意一个字符

分别传入grep得模式

y.

y.. 任意2个字符

实践代码

匹配符合模式 .ac 的行

.$ 匹配任意字符结尾

拿到每一行的结尾

. 和转义符

只想拿到每一行结尾的普通小数点., 需要对点转义

\转义符

转义字符,让有特殊意义的字符,现出原形,还原其本义
如
\.  还原为小数点

空格,换行,tab

\n  匹配换行符
\b  匹配单词边界,如我想从字符串“This is Regex”匹配单独的单词 “is”正则就要写 "\bis\b"

\r  匹配回车符
\t  匹配一个横向的制表符

* 星号

重复前一个字符0次或n次

.* 符

匹配任意字符

.表示任意字符,*表示匹配前一个字符0次或多次
因此放一起,代表匹配每一行所有内容,包括空格,没有空行

^.* 符

语法

^.* 表示以任意多个字符开头的行

基础用法,^.*

找出任意以字母i开头的行,且匹配后续所有内容

加大难过
找出任意以字母i开头的行,且以h结尾的行

.*$ 符

以任意多个字符结尾的行

你可以加上条件,例如 p.*$

以p.*$结尾的行
等于,匹配出从p到结尾的所有内容

[ ]中括号

中括号,有如下用法

[abc]

【abc】匹配括号内的小写a,b,c字符

关于到大小写的精准匹配,就别添加忽略大小写参数了

[a-z] , [A-Z],[a-zA-Z],[0-9]

[a-z]  匹配所有小写单个字母

[A-Z]  匹配所有单个大写字母

[a-zA-Z]  匹配所有的单个大小写字母

[0-9]  匹配所有单个数字

[a-zA-Z0-9]  匹配所有数字和字母
[a-z] 匹配小写字母

[A-Z] 匹配大写字母

[a-z0-9] 匹配小写字母和数字

[0-9A-Z] 匹配大写字母和数字

[a-z0-9A-Z] 匹配大写,小写字母,数字

abc 中括号取反

语法

[^abc] 排除中括号里的a,b,c,和单独的^符号,作用是不同的
[^a-z] 排除小写字母

{ } 花括号(扩展正则)

a\{n,m\}

a\{n,m\}  重复字符a,n到m次

a\{1,3} 重复字符a,1到3次
实践
测试数据
[root@bogon test]# cat chaoge777.txt 
I am teacher yuchao.
I teach linux,python!

I like english

My website is http://yuchaoit.cn
Our school site is https://apecome.com
My qq num is 877348180

my qq num is not  87777773333344444888811188880000

Goog good study , day day up!

正则

8\{1,3\}
匹配数字8一次到3次

每次最少找出2个8,最多3个8

8\{2,3\}

grep 默认不认识扩展正则 {}

grep默认不认识扩展正则{},识别不到它的特殊作用,因此只能用转义符,让他成为有意义的字符

办法1
使用转义符 \{\}

办法2,让grep认识花括号,可以省去转义符
使用egrep命令
或者 grep -E

实践

a\{n,\}
重复a字符至少n次,可以用简写了

a\{n\}
重复字符a,正好n次

a\{,m\}
匹配字符a最多m次

扩展正则表达式(ERE)

这样记忆就好
基于正则表达式
属于早期正则表达式,支持一些基本的功能
与grep,sed命令结合使用

扩展正则表达式
后来添加的正则表达式
和grep,awk命令结合

+ 加号

语法
+
重复前一个字符1次或多次
注意和*的区别,*是0次或多次

匹配一次或者多次0,没有0的行是不会显示的

0+
找出一个,或者多个数字零

[0-9]+
从文中找出连续的数字,排除字母,特殊符号,空格

[a-z]+
找出连续的小写字母,排除大写字母,标点符号,数字

[root@bogon test]# grep -E "[a-z]+" chaoge777.txt -no
1:am
1:teacher
1:yuchao
2:teach
2:linux
2:python
4:like
4:english
6:y
6:website
6:is
6:http
6:yuchaoit
6:cn
7:ur
7:school
7:site
7:is
7:https
7:apecome
7:com
8:y
8:qq
8:num
8:is
10:my
10:qq
10:num
10:is
10:not
12:oog
12:good
12:study
12:day
12:day
12:up

[A-Za-z0-9]+
注意,这里添加了+号,就是找的连续的字母数字了,缺少+号则是每次匹配单个字符

[^A-Za-z0-9]+
此写法,找出除了数字,大小写字母意外的内容,如空格,标点符号
可以使用-o参数,看到每次匹配的内容

*和+的区别

语法
*是重复0次,重复多次,因此没匹配到的行也就过滤出来了

+是重复1次,多次,因此至少匹配到1次才看到

例如,我们来找到字母o,看如下2个写法

go*d和go+d?d的区别

准备测试数据
[root@bogon test]# cat god.log 
I am God, I need you to good good study and day day up, otherwise I will send you to see Gd,oh sorry, gooooooooood!

关于寻找god,gooooood,gd的区别

go*d 可以有0个或者n个字母o
go*d 可以找到god,doof,gd,gooooooood

go+d 可以有一个或n个字母o
go+d 可以找到god,good,gooooooood

go?d 可以找到0个或者1个字母0
go?d 可以找到gd,god

| 或者符

竖线在正则里是或者的意思

查看内存信息

找出文件中的空行以及注释行

测试数据
[root@bogon test]# cat chaoge999.txt 
I am teacher yuchao.
I teach linux,python!

I like english

My website is http://yuchaoit.cn
Our school site is https://apecome.com
My qq num is 877348180

my qq num is not  87777773333344444888811188880000

#Goog good study , day day up!
#
#hello  halo

( )括号,分组符

语法
()作用是将一个或者多个字符捆绑在一起,当做一个整体进行处理

小括号功能之一是分组过滤被括起来的内容,括号内的内容表示一个整体

括号()内的内容可以被后面的"\n"正则引用,n位数字,表示引用第几个括号的内容

\1: 表示从左侧起,第一个括号中的模式所匹配到的字符
\2: 从左侧器,第二个括号中的模式所匹配到的字符

分组基本用法

测试数据
[root@bogon test]# cat godd.log 
I am God, I need you to good good study and day day up, otherwise I will send you to see Gd,oh sorry, gooooooooood!
I am glad to see you, god,you are a good god!

要求仅仅匹配出glad和good
尝试使用正则
grep -iE "gla|ood" godd.log

并非我们想要的数据
我想要的是例如这样的匹配,只找出good,glad
grep -iE "glad|good" godd.log

可以使用分组写法
grep -iE "g(la|oo)d" godd.log

分组与向后引用

语法
()
分组过滤,被括起来的内容表示一个整体,另外()的内容可以被后面的\n引用,表示引用第几个括号的内容

\n
引用前面()里的内容,例如(abc)\1 表示匹配abcabc
测试数据
[root@bogon test]# cat lovers.log 
I like my lover.
I love my lover.
He likes his lovers.
He love his lovers.

分组正则,提取love出现2次的行
拆解
love,可以写为l..e

提取/etc/passwd
找出系统中几个特殊shell,专门用来开机,关机的用户
特点是,用户名,登录shell名字一样
可以用分区提取出

分组正则,提取特殊用户

这部分正则需要拆开,更容易理解
1.提取冒号以外的字符,使用+可以匹配更多字母,没必要每次只处理一个
grep -iE "[^:]+" /etc/passwd

2.使用\b匹配单词边界,提取出单词,示例用法,通常英文单词的边界是空格,标点符号
[root@bogon test]# echo  'my name is jie,everyone call me jiege' |grep -iE "jie\b" -o
jie

3.继续提取用户文件,来确定第一个单词的边界

解释上图
正则拆解,根据写的顺序去理解
[^:]+  找出除了冒号以外的连续字符
^([^:]+\b)  对连续字符分组,且设定开头错点,以及单词边界,grep -Ei "^([^:]+\b)" /etc/passwd  这就等于找出第一个单词了
"^([^:]+\b).*\1$"  找出如sync.*sync 这样(开头).*(结尾)的内容,使用分组,以及 \1 引用的语法

正则表达式总结

基础正则 BRE
^
$
.
*
.*
[abc]
[^abc]
\{n,m\}

BRE语法

. 匹配单个任意字符,匹配 . 本身使用 \.

*  前面的字符或模式重复任意次,匹配 * 本身使用 \*

\{m\}  前面的字符或模式重复m次

\{m,n\}  前面的字符或模式重复m到n次

\{m,\}  前面的字符或模式重复m次以上

\(regexp\) 分组,将\(和\)之间的内容视为一个整体,有两个作用
1,配合前面的 * \{m,n\} 等量词使用,例如:ab\{2\} 匹配“abc”,而 \(ab\)\{2\}匹配“abab”
2,向后引用(back references),使用\1 ~ \9 来引用第1~9个分组匹配的内容
3.例如:\(ab*\)\1 可以匹配“abab”, 也能匹配“abbbabbb”


^  放在正则表达式开头则匹配行首,其他位置匹配 ^ 本身

$  放在正则表达式末尾则匹配行尾,其他位置匹配 $ 本省

[list]  自定义字符集,可以匹配 [ 和 ]之间出现的任意字符,例如:a[bcd] 可以匹配“ad,ac”或“cabba”

且支持使用char1-char2这种省略写法,例如:[0-9]* 可以匹配“1234567890”,[a-c]* 可以匹配“cabba”

[^list] 同上,^取反的作用,匹配所有没有出现在 [ 和 ] 之间的其他字符

另外其他风格的正则表达式中有诸如 \d \w \s 等速记符号(shorthand)表示一些常用字符集,BER和ERE均不支持这种写法,取而代之的是POSIX标准中定义的字符集:

POSIX正则语法表

POSIX	Description	ASCII	Shorthand
[:alnum:]	数字和字母	[a-zA-Z0-9]	
[:alpha:]	字母	[a-zA-Z]	
[:ascii:]	ASCII字符	[\x00-\x7F]	
[:blank:]	空格和 Tab	[ \t]	\h
[:cntrl:]	控制字符	[\x00-\x1F\x7F]	
[:digit:]	数字	[0-9]	\d
[:graph:]	可视字符	[\x21-\x7E]	
[:lower:]	小写字母	[a-z]	\l
[:print:]	可打印字符	[\x20-\x7E]	
[:punct:]	标点符号	[!"#$%&'()*+, -./:;<=>?@[ ]^_‘{\	}~]	
[:space:]	所有空白字符	[ \t\r\n\v\f]	\s
[:upper:]	大写字母	[A-Z]	\u
[:word:]	单词	[A-Za-z0-9_]	\w
[:xdigit:]	十六进制数	[A-Fa-f0-9]

注意:[ 和 ] 也是该字符集名称的一部分,即在使用中和 [0-9] 等价的是 [[:digit:]] 而不是 [:digit:]

ERE语法

ERE和BRE的最显著的区别是ERE中所有元字符(metacharacters)均不需要使用 \ 进行转义,即用 {m,n} 替代 \{m,n\} , (regexp) 替代 \(regexp\) (当然分组向后引用依旧是 \1 ~ \9)。

此外ERE还在BRE基础上增加了以下语法:

? 前面的字符或模式重复0或1次

+ 前面的字符或模式重复1次及以上

|,regexp1|regexp2匹配regexp1或regexp2

GNU扩展的BRE

实际上现代Linux发行版中使用的 grep sed awk 等工具均由GNU提供,GNU在实现对BRE进行了扩展,增加了 \?  \+  \| 使得BRE和ERE的区别仅剩元字符是否需要转义

个人认为,BRE现在存在的主要意义还是向下兼容,避免修改已经投入使用的正则表达式

总结grep

egrep被淘汰,使用grep -E
可以使用grep -o参数,查找每次匹配的结果
正则需要在练习中理解器含义,无法死记硬背
后面结合sed,awk发挥更多正则作用

正则记忆表

标签:字符,grep,log,正则表达式,正则,linux,匹配
来源: https://www.cnblogs.com/yujiejie/p/16136406.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有