5.正则表达式 过滤文本

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

正则表达式被很多程序和开发语言所广泛支持:vim, less,grep,sed,awk, nginx,mysql 等

主要用来匹配字符串(命令结果,文本内容)

通配符匹配文件(而且是已存在的文件)

  • 基本正则表达式

  • 扩展正则表达式

可以使用

man 7 regex
可以使用 man手册帮助

 

5.1.1 元字符(字符匹配)

元字符:

.   匹配任意单个字符,可以是一个汉字  
[]   匹配指定范围内的任意单个字符,示例:[zhou]   [0-9]   []   [a-zA-Z]   [:alpha:]
[^] 匹配指定范围外的任意单个字符,示例:[^zhou] [^a.z] [a.z]
[: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 正则表达式会匹配全角空格符

元字符点(.)

[root@localhost ~]#ls /etc/|grep rc[.0-6]
#此处的点代表字符 将列出/etc/目录下以"rc"开头,后面跟随一个数字或一个小数点并具有0到6的范围的文件或目录。
rc0.d
rc1.d
rc2.d
rc3.d
rc4.d
rc5.d
rc6.d
rc.d
rc.local

image-20230816155213057

[root@localhost ~]#ls /etc/ | grep 'rc\.'
#点值表示点需要转义
rc.d
rc.local

image-20230816155252515

[root@localhost ~]# grep r..t /etc/passwd         
#r..t ..代表任意两个字符    
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

image-20230816155910957

[root@localhost ~]# echo abc |grep a.c              
#表示原来的点需要加\转义
abc
[root@localhost ~]# echo abc |grep a\.c
#不加引号有时匹配会有出入
abc
[root@localhost ~]# echo abc |grep 'a\.c'          
#标准格式需要加'' 或者""

image-20230816173513023

image-20230816173629837

[root@localhost ~]# ls |grep '[zhou].txt'    
#匹配[]中任意一个字符
h.txt
o.txt
u.txt
z.txt
[root@localhost ~]# ls [a-d].txt                
#通配符
a.txt A.txt b.txt B.txt c.txt C.txt d.txt
[root@localhost ~]# ls |grep '[a-d].txt'            
#真正的小写在正则表达式中
a.txt
b.txt
c.txt
d.txt

image-20230816184215261

image-20230816185354212

image-20230816185301483

[root@localhost ~]# ls |grep '[^a-z].txt'   
#显示非小写字母
A.txt
B.txt

[root@localhost ~]# ls |grep '[^a.z].txt'    
#[]里就是本意不需要转义

[[:space:]]空格
命令用于在文件zhen.txt中搜索包含空白字符(空格、制表符、换行符等)的行。[[:space:]]是一个正则表达式模式,表示匹配任何空白字符。
[root@localhost ky15]#grep [[:space:]] zhen.txt
hhh  
jj l
kkk  
[root@localhost ky15]#grep [[:space:]] zhen.txt |cat -A
hhh  $
jj^I^Il$
kkk  $


[root@localhost ~]#ls /etc/ |grep "rc[.0-6]"
[root@localhost ~]#ls /etc/ |grep "rc[.0-6]."

#注意点的转意

image-20230816190000636

 

image-20230816191049516

image-20230816191108452

image-20230816190954954

 

image-20230816191410834

5.1.2 表示次数

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

 

举例:

[0-9]   [0 1 2 3 4 5  6 7 8 9]



[root@localhost ~]# ifconfig eth0|grep netmask|grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+'|head -n1
192.168.1.100

[root@localhost ~]# ifconfig eth0|grep netmask|grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+'
192.168.1.100
255.255.255.0
192.168.1.255

image-20230819113647798

[root@localhost ~]# echo google |grep 'go\{2\}gle'
#带表前面的o出现2次
google
[root@localhost ~]# echo gooooogle |grep 'go\{2,\}gle'  
#带表前面的o出现2次以上
gooooogle

image-20230819114351192

[root@localhost ~]# echo gooooogle |grep 'go\{2,5\}gle'
#带表前面的o出现2次以上5次以下
gooooogle
[root@localhost ~]# echo goooooogle |grep 'go\{2,5\}gle
[root@localhost ~]#

image-20230819114915181

[root@localhost ~]# echo goooooogle |grep 'go*gle'    
#表示0次到任意次
goooooogle
[root@localhost ~]# echo ggle |grep "go*gle"
ggle
[root@localhost ~]# echo gggle |grep "go*gle"    
#grep 包含最前面的g不匹配
gggle
[root@localhost ~]# echo gdadadadgle |grep "g.*gle"    
#.*代表任意匹配所有
gdadadadgle

image-20230819115613758

[root@localhost ~]# echo ggle |grep "go\?gle"      
# \?一次或者0次
ggle
[root@localhost ~]# echo gogle |grep "go\?gle"
gogle

image-20230819115835112

[root@[root@localhost ~]# echo google |grep "go\+gle"   
#一个以上
google
[root@localhost ~]# echo gogle |grep "go\+gle"
gogle
[root@localhost ~]# echo ggle |grep "go\+gle"
[root@localhost ~]# echo google |grep "go\?gle"

image-20230819121834984

5.1.3位置锚定

^ #行首锚定, 用于模式的最左侧 $ #行尾锚定,用于模式的最右侧 ^PATTERN$ #用于模式匹配整行 (单独一行 只有root) ^$ #空行 ^[[:space:]]*$ # 空白行

< 或 \b #词首锚定,用于单词模式的左侧(连续的数字,字母,下划线都算单词内部) > 或 \b #词尾锚定,用于单词模式的右侧 <PATTERN> #匹配整个单词

例子:

思考过滤出不是已#号开头的非空行
[root@localhost opt]# grep "^[^#]" /etc/fstab

image-20230819125020056

 

[root@localhost ~]# cp /etc/passwd /opt/
[root@localhost ~]# cd /opt/
[root@localhost opt]# echo root >> passwd
[root@localhost opt]# cat passwd |grep "^root$"
root

^PATTERN$ #用于模式匹配整行 (单独一行 只有root)

image-20230819123043400

[root@localhost opt]# grep "^[[:space:]]*$" /etc/fstab 

^[[:space:]]*$ # 空白行

image-20230819125822464

[root@localhost ~]#echo hello-123 |grep "\<123"
#除了 字母 数字 下划线其他都算 单词的分隔符
hello-123
[root@localhost ~]#echo hello 123 |grep "\<123"
hello 123

image-20230819130752597

5.1.4分组或其他

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

后向引用:分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名

方式为: \1, \2, \3, ...

\1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符

或者

或者:\|

示例

[root@localhost ~]#echo abccc |grep "abc\{3\}"
abccc
#c出现三次

[root@localhost ~]#echo abcabcabc |grep "\(abc\)\{3\}"
#分组 匹配abc   \( \)为转义符防止grep把(abc)当作整体过滤
abcabcabc

image-20230819131526037

[root@localhost ~]#echo 1abc |grep  "1\|2abc"
#只匹配了1
1abc

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

image-20230819132230837

[root@localhost opt]# ifconfig eth0 | grep netmask | grep -o '\([0-9]\{1,3\}\.\)\{3\}[0-9]\{3\}'|head -1
192.168.1.100


[root@localhost opt]# ifconfig eth0 |grep netmask|grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'|head -1
192.168.1.100



[root@localhost opt]# ifconfig eth0 |grep netmask|grep -Eo '([0-9]{1,3}.){4}'
192.168.1.100
255.255.255.0
192.168.1.255

#-E 开启扩展正则表达式 (表示字符相差不大)

image-20230819133341228

 

5.1.5 扩展正则表达式(表示字符相差不大)

grep -E 开启扩展正则表达式

egrep 开启扩展正则表达式

 

表示次数

  • 匹配前面字符任意次 ? 0或1次

  • 1次或多次 {n} 匹配n次 {m,n} 至少m,至多n次 {,n}  #匹配前面的字符至多n次,<=n,n可以为0 {n,} #匹配前面的字符至少n次,<=n,n可以为0

 

表示分组

() 分组 分组:() 将多个字符捆绑在一起,当作一个整体处理,如:(root)+ 后向引用:\1, \2, ... | 或者 a|b #a或b C|cat #C或cat (C|c)at #Cat或cat

 

练习操作:

1表示qq号

[root@localhost ~]# echo "12819175222" | grep "\b[0-9]\{6,12\}\b"
12819175222

image-20230819134141195

 

2.表示邮箱

echo "gui@qq.com" |grep -E "[[:alnum:]_]+@[[:alnum:]_]+\.[[:alnum:]_]+" 

[:alnum:] 字母和数字

3.表示手机号

echo "13705174391"|grep -E "\b1[3456789][0-9]{9}\b"