基础正则
REGEXP: Regular Expressions,由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意义,而表示控制或通配的功能,类似于增强版的通配符功能,但与通配符不同,通配符功能是用来处理文件名,而正则表达式是处理文本内容中字符。
正则表达式被很多程序和开发语言所广泛支持:vim, less,grep,sed,awk, nginx,mysql 等
正则表达式的主要作用是:匹配字符串(命令结果、文本内容)
通配符的作用是:匹配已存在文件名
正则表达式的分类:
- 基础正则表达式(BRE:basic regular expression)
- 扩展正则表达式(ERE:extended regular expression)
- 编程语言支持的高级正则表达式
grep sed 默认使用基础正则表达式grep -E 、 sed -r 、 egrep 、 awk 扩展正则表达式
搜索字符的方式
1. 精确搜索
2.正则表达式搜索
- 元字符:预定义好的具有特殊含义的符号,这些符号能够进行通配
- 可读性非常的差
- 写正则表达式不难
1.1元字符
- abc 匹配字符串"abc",普通字符的匹配
- [abcde...] :匹配中括号内的任意单个字符
- \n :匹配换行符
- \t :匹配制表符
- \w :匹配单词字符 [a-zA-Z0-9_]
- \W :匹配非单词字符 [^a-zA-Z0-9_]
- \s :匹配空白字符
- \S :匹配非空白字符
- \d :匹配数字
- \D :匹配非数字
- . 表示匹配任意单个字符
元字符点(.)
示例:
[root@localhost ~]#ls /etc/|grep rc[.0-6]
#此处的点代表字符
rc0.d
rc1.d
rc2.d
rc3.d
rc4.d
rc5.d
rc6.d
rc.d
rc.local
[root@localhost ~]#ls /etc/|grep rc.
#此处的点代表任意单个字符
#rc. 表示过滤出含有rc后面任意单个字符的行
rc0.d
rc1.d
rc2.d
rc3.d
rc4.d
rc5.d
rc6.d
rc.d
rc.local
[root@localhost ~]#ls /etc/ | grep 'rc\.'
#点值表示点需要转义,要加引号
rc.d
rc.local
[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
[root@localhost ~]#cat 1.txt
abc
adc
a.c
asdc
[root@localhost ~]#grep a.c 1.txt
#表示原来的点需要加\转义
abc
adc
a.c
[root@localhost ~]#grep a\.c 1.txt
#不加引号有时匹配会有出入
abc
adc
a.c
[root@localhost ~]#grep 'a\.c' 1.txt
a.c
#标准格式需要加'' 或者""
[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
[root@localhost ~]# ls |grep '[^a-z].txt'
#显示非小写字母
A.txt
B.txt
[root@localhost ~]# ls |grep '[^a.z].txt'
#[]里就是本意不需要转义
#这段表示过滤出除了a.txt,..txt ,z.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 $
字符组
- x[abc]z :可以匹配包含"xaz"、"xbz"、"xcz"的字符串
- 取反表示法:中括号内开头使用 ^ ,表示只要不是中括号中的字符就匹配
- 范围表示法:
- 特殊元字符在中括号中的匹配:
想要在括号中匹配^,可以加上转义符或者在中括号中放在非开头位置,如[\^a],[a^]
字符类
字符类 | 含义 |
---|---|
[:lower:]
|
等价于
a-z
|
[:upper:]
|
等价于
A-Z
|
[:alpha:]
|
等价于
A-Za-z
,也等价于
[:lower:]
+
[:upper:]
|
[:digit:]
|
等价于
0-9
|
[:alnum:]
|
等价于
0-9A-Za-z
,也等价于
[:lower:]
+
[:upper:]
+
[:digit:]
|
[:xdigit:]
|
匹配十六进制数字
0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f
|
[:blank:]
|
匹配空格或制表符
|
[:space:]
|
匹配空格、制表符、换行符、换页符、垂直制表符、回车符等等所有空白符号
|
[:punct:]
|
(Punctuation)
匹配所有标点符号,
! " # $ % & ' ( ) * + , - . / : ; < = > ?
@ [ \ ] ^ _ ` {
|
[:print:]
|
可打印字符,等价于
[:alnum:]
+
[:punct:]
+
空格
|
[:graph:]
|
图形字符,即能展现字符颜色的符号,等价于
[:alnum:]
+
[:punct:]
|
[:cntrl:]
|
所有的控制符号,八进制的
000
到
037,
以及
177 (
DEL
)
|
- [[:alpha:]] :任一字母
- [^[:alpha:]] :任一非字母
- [^[:alpha:]0-3] :任一非字母且非0 1 2 3
echo "aāá ǎ à" | grep '[[=a=]]'
1.2 表示匹配次数
量词
* | 匹配前面字符出现 0 到正无穷,包括0次,贪婪模式:尽可能长的匹配 |
.* | 任意长度的任意字符 不包括0次 1到正无穷 |
\? | 匹配其前面的字符出现0次或1次,即:可有可无 |
\+ | 匹配其前面的字符出现最少1次,即:肯定有且 >=1 次 到正无穷 |
\{n\} | 匹配前面的字符n次 |
\{m,n\} | 匹配前面的字符至少m次,至多n次 |
\{,n\} | 匹配前面的字符至多n次,<=n |
\{n,\} | 匹配前面的字符至少n次 |
使用grep加-E 即可不用转义{}
举例:
[root@localhost ~]# echo google |grep 'go\{2\}gle'
#带表前面的o出现2次
google
[root@localhost ~]# echo gooooogle |grep 'go\{2,\}gle'
#带表前面的o出现2次以上
gooooogle
[root@localhost ~]# echo gooooogle |grep 'go\{2,5\}gle'
#带表前面的o出现2次以上5次以下
gooooogle
[root@localhost ~]# echo goooooogle |grep 'go\{2,5\}gle'
[root@localhost ~]#
[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
[root@localhost ~]# echo ggle |grep "go\?gle"
# \?一次或者0次
ggle
[root@localhost ~]# echo gogle |grep "go\?gle"
gogle
[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"
[root@localhost ~]#echo abc|grep "[abc]\{3\}"
#需要加引号
#他的 匹配思路是 [abc]\{3\} 在匹配abc的时候
#第一轮 看 首字母 是否有abc中的一个, 第二轮也是看是否有abc中的一个 第三轮也是看是否有abc中的一个
实例:如何使用grep过滤出当前主机的IP地址
方法一、
ifconfig ens33|grep netmask|grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+'|head -n1
扩展正则
ifconfig ens33|grep netmask|grep -Eo '[0-9]+.[0-9]+.[0-9]+.[0-9]+'|head -n1
方法二、
ifconfig ens33|grep netmask|grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'|head -n1
ifconfig ens33|grep netmask|grep -Eo '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'|head -n1
1.3 位置匹配(锚定)
^ | 行首锚定, 用于模式的最左侧 表示开头 |
$ | 行尾锚定,用于模式的最右侧 表示结尾 |
^字符$ | 匹配只有 此字符 的 行(^root$ 匹配只有root的行) |
^$ | 空行 |
^[[:space:]]*$ | 空白行 |
\< 或 \b | 词首锚定,用于单词模式的左侧(连续的数字,字母,下划线都算单词内部) |
\> 或 \b | 词尾锚定,用于单词模式的右侧 |
\<PATTERN\> | 匹配整个单词 |
例子:
思考过滤出不是已#号开头的非空行
[root@localhost ~]#grep "^[^#]" /etc/fstab
[root@localhost data]#cat test.txt
google
googler
ggoogle
ggler
[root@localhost data]#grep '^google$' test.txt
google
#只匹配google 这个字符
匹配空白行
[root@localhost data]#grep "^[[:space:]]*$" /etc/fstab
[root@localhost data]#
[root@localhost ~]#echo hello-123 |grep "\<123"
#除了 字母 数字 下划线其他都算 单词的分隔符
hello-123
[root@localhost ~]#echo hello 123 |grep "\<123"
hello 123
1.4 分组或其它
分组:( ) 将多个字符捆绑在一起,当作一个整体处理,如:\(root\)+
后向引用:分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名
反向引用对应的分组的匹配结果
方式为: \1, \2, \3, ... 分组 (\ 为转义符)
\1 表示第一个分组表达式的匹配结果
\2 表示第二个分组表达式的匹配结果
根据左括号的位置决定第几个分组。
例如: (abc)def 、 ([a-d] ){3} 、 (([0-9])abc(def){2})(hgi)
注意:反向引用所引用的是分组匹配后的结果,不是分组表达式。
[root@localhost data]#echo "abc and abcxyz" | grep -E "(abc|def) and \1xyz"
abc and abcxyz
[root@localhost data]#echo "abc and defxyz" | grep -E "(abc|def) and \1xyz"
[root@localhost data]#
#把abcxyz改为defxyz后就无法匹配了。
方法一、
[root@localhost data]#echo "abc and defxyz" | grep -E "(abc|def) and (abc|def)xyz"
abc and defxyz
方法二、
[root@localhost data]#echo "abc and defxyz" | grep -P '(abc|def) and \1xyz'
#无法匹配
[root@localhost data]#echo "abc and defxyz" | grep -P '(abc|def) and (?1)xyz'
abc and defxyz
或者:二选一表达式
\| (\表示转义符)
示例:
[root@localhost ~]#echo abccc |grep -E "abc{3}" #c出现三次
abccc
[root@localhost ~]#echo abcabcabc |grep -E "(abc){3}"
#分组 匹配abc 把abc当作一个整体
abcabcabc
[root@localhost ~]#echo 1abc |grep -E "1|2abc"
#只匹配了1
1abc
#这段的意思是匹配 1 或 2abc
[root@localhost ~]#echo 1abc |grep -E "(1|2)abc"
#1abc或者2abc
1abc
-E 是扩展正则 ,不用在()|前面加上转义符
实例:如何使用grep过滤出当前主机的IP地址
方法三:
ifconfig ens33 |grep netmask|grep -Eo '([0-9]{1,3}.){4}'|head -n1
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
grep -E 实例:
[root@localhost data]#echo abcabcabc|grep "(abc){3}"
#输入此命令无法过滤 ,因为基础正则无法识别 (){},可以在前面加上转义符或使用扩展正则。
[root@localhost data]#echo abcabcabc|grep "\(abc\)\{3\}"
abcabcabc
[root@localhost data]#echo abcabcabc|grep -E "(abc){3}"
abcabcabc
1、表示qq号
[root@localhost ~]#echo "940132245" |grep "\b[0-9]\{6,12\}\b"
#要加\b 如果不加要是有其它跟qq号一样格式的数并且前面还带字母,这样也会被匹配进去
如:
[root@localhost data]#echo "awf940132245" |grep "[0-9]\{6,12\}"
awf940132245
#匹配了一个和qq号无关的数。
[root@localhost data]#echo "awf940132245" |grep "\b[0-9]\{6,12\}\b"
[root@localhost data]#
#可以看到没有匹配成功。
[root@localhost data]#echo "awf 940132245" |grep "\b[0-9]\{6,12\}\b"
awf 940132245
2、表示邮箱
echo "zhou@qq.com" |grep -E "[[:alnum:]_-]+@[[:alnum:]_]+\.[[:alnum:]_]+"
3、表示手机号
echo "13705173391"|grep -E "\b1[3456789][0-9]{9}\b"
正则表达式的匹配过程
- 扫描第一个字符,和正则表达式的第一个元素进行匹配
- 如果匹配失败,则意味着这一轮的正则匹配失败
- 扫描下一个字符,从头开始和正则表达式进行匹配
- 如果匹配成功,则继续扫描下一个字符和正则表达式的下一个元素进行匹配
- 如果这一轮正则匹配成功,则不交还匹配成功的字符
- 然后从匹配成功的下一个字符进入下一轮匹配
- 某轮正则匹配成功,则消耗所有匹配成功的字符
- 某轮匹配失败,则消耗本轮匹配的首字符,剩余的字符被交还
grep 基本使用
格式:grep [选项]… 查找条件 目标文件
选项:
-m 数字 | 匹配的行数,匹配#次后停止 |
-i | 忽略字符大小写 |
-n | 显示匹配的行号 |
-c | 统计匹配的行数 |
-o | 仅显示匹配到的字符串(仅显示匹配的内容) |
-q | 静默模式,不输出任何信息(写脚本用) |
-f | 匹配两个文件相同的行 grep -f A B |
-r | 递归目录,但不处理软链接 开始搜索目录 |
-R | 递归目录,但处理软链接 |
-w | 匹配整个单词 |
-A 数字 | 显示匹配行及后 数字 行(如:后3行) |
-B 数字 | 显示匹配行及前 数字 行(如:前3行) |
-C 数字 | 显示匹配行及前后 数字 行(如:前3行和后3行) |
-E | 使用ERE(扩展正则),相当于egrep |
-F | 不支持正则表达式,相当于fgrep |
-e | 实现多个选项间的逻辑or关系,如:grep –e ‘cat ' -e ‘dog' file 包含cat或者包含dog的行 |
关于grep -m
[root@localhost ~]#grep -m 1 da /etc/passwd #多个匹配只取第一个
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@localhost ~]#grep -m 2 da /etc/passwd #多个匹配只取两个
daemon:x:2:2:daemon:/sbin:/sbin/nologin
libstoragemgmt:x:998:996:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
关于-A ,-B ,-C
grep -A 3 root /etc/passwd #匹配到的行后3行业显示出来
[root@localhost ~]#grep -A3 root /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
--
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
grep -B 3 games /etc/passwd #匹配到的行前3行业显示出来
[root@localhost ~]#grep -B3 games /etc/passwd
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
grep -C 2 games /etc/passwd #匹配到的行前2行 后2行业显示出来
[root@localhost ~]#grep -C2 games /etc/passwd
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
关于 -w
[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
[root@localhost ~]#grep -w r..t /etc/passwd #过滤出r和t之间有两个字符 单词 的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost ~]#useradd rooter
[root@localhost ~]#grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
rooter:x:1003:1003::/home/rooter:/bin/bash
[root@localhost ~]#grep -w root /etc/passwd #过滤出只有root整个单词的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
其它:
[root@test1 opt]# cat 123.txt |grep -v '^$' >test.txt //将非空行写入到test.txt文件
[root@test1 opt]# grep "^b" 123.txt //过滤已b开头
[root@test1 opt]#grep '/$' 123.txt //过滤已/结尾
[root@test1 opt]# grep -v "^$" 123.txt //过滤非空行3 备份与
[root@localhost yum.repos.d]# ifconfig ens33 |grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+"
192.168.91.100
255.255.255.0
192.168.91.255
[root@localhost yum.repos.d]# ifconfig ens33 |grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+"|head -1
192.168.91.100
###面试题 统计当前主机的连接状态
[root@localhost ~]# ss -nta | grep -v '^State' |cut -d" " -f1|sort |uniq -c
3 ESTAB
17 LISTEN
#####统计当前连接主机数
[root@localhost ~]#ss -nt |tr -s " "|cut -d " " -f5|cut -d ":" -f1 |sort|uniq -c
3 192.168.91.1
1 192.168.91.101
1 Address