目录
REGEXP: Regular Expressions,由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符),不表示字符字面意义,而表示控制或通配的功能,类似于增强版的通配符功能,但与通配符不同,通配符功能是用来处理文件名,而正则表达式是处理文本内容中字符
正则表达式被很多程序和开发语言所广泛支持:vim, less,grep,sed,awk, nginx,mysql 等
主要用来匹配字符串(命令结果,文本内容),
通配符匹配文件(而且是已存在的文件)
-
基本正则表达式
-
扩展正则表达式
可以使用man 7 regex手册帮助
正则表达式之
元字符
元字符是一个或一组代替一个或多个字符的字符。
. 匹配任意单个字符,可以是一个汉字
[] 匹配指定范围内的任意单个字符,示例:[zhou] [0-9] [] [a-zA-Z]
[^] 匹配指定范围外的任意单个字符,示例:[^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]
#这里点代表字符
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 data]#touch {a..z}.txt
[root@localhost data]#ls
a.txt b.txt dns.sh e.txt g.txt i.txt k.txt m.txt o.txt q.txt s.txt u.txt w.txt y.txt
[a..z].txt c.txt d.txt f.txt h.txt j.txt l.txt n.txt p.txt r.txt t.txt v.txt x.txt z.txt
#匹配[]中任意一个字符[root@localhost data]#ls |grep '[bin].txt' b.txt i.txt n.txt
#匹配不是a-z.txt文件
[root@localhost data]#ls |grep [^a-z].txt [a..z].txt {a-z}.txt {a-Z}.txt
表示次数
* | 匹配前面的字符任意次,包括0次,贪婪模式:尽可能长的匹配 |
.* | 任意长度的任意字符 |
\? | 匹配其前面的字符出现0次或1次,即:可有可无 |
\+ | 匹配其前面的字符出现最少1次,即:肯定有且 >=1 次 |
\{n\} | 匹配前面的字符n次 |
\{m,n\} | 匹配前面的字符至少m次,至多n次 |
\{,n\} | 匹配前面的字符至多n次,<=n |
\{n,\} | 匹配前面的字符至少n次 |
##代表前面的o出现3次以上
[root@localhost data]#echo goooooogle |grep 'go\{3,\}gle'
goooooogle
#代表前面o出现2次以上4次以下
[root@localhost data]#echo google |grep 'go\{2,4\}gle'
google
#代表o匹配任意次
[root@localhost data]#echo goooooogle |grep go*gle
goooooogle
#一个以上
[root@localhost data]#echo google |grep "go\+gle"
google
位置锚定
^ | 行首锚定, 用于模式的最左侧 |
$ | 行尾锚定,用于模式的最右侧 |
^PATTERN$ | 用于模式匹配整行 (单独一行 只有root) |
^$ | 空行 |
^[[:space:]]*$ | 空白行 |
\< 或 \b | 词首锚定,用于单词模式的左侧(连续的数字,字母,下划线都算单词内部) |
\> 或 \b | 词尾锚定,用于单词模式的右侧 |
\<PATTERN\> | 匹配整个单词 |
#过滤出不是已#号开头的非空行
[root@localhost data]#grep "^[^#]" /etc/fstab
/dev/mapper/centos-root / xfs defaults 0 0
UUID=3485d403-cf78-4d1b-92c9-b6025ccacf17 /boot xfs defaults 0 0
/dev/mapper/centos-swap swap swap defaults 0 0
#过滤非空行
[root@localhost data]#grep "^[^$]" /etc/fstab
#
# /etc/fstab
# Created by anaconda on Thu Oct 7 02:46:55 2021
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root / xfs defaults 0 0
UUID=3485d403-cf78-4d1b-92c9-b6025ccacf17 /boot xfs defaults 0 0
/dev/mapper/centos-swap swap swap defaults 0 0
分组和其他
分组:() 将多个字符捆绑在一起,当作一个整体处理,如:(root)+
后向引用:分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为: \1, \2, \3, ...,\1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符
# 分组,分成三组和分成俩组
#提取ip地址(匹配数字)
[root@localhost data]#ifconfig ens33 |grep netmask|grep -Eo '([0-9]{1,3}.){4}' 192.168.37.102 255.255.255.0 192.168.37.255
[root@localhost data]#ifconfig ens33|grep netmask|grep -o '\([0-9]\{1,3\}\.\)\{3\}[0-9]\{3\}'|head -1 192.168.37.102
扩展正则表达式
表示次数
* 匹配前面字符任意次
? 0或1次
+ 1次或多次
{n} 匹配n次
{m,n} 至少m,至多n次
{,n} #匹配前面的字符至多n次,<=n,n可以为0
{n,} #匹配前面的字符至少n次,<=n,n可以为0
#匹配oo字符和出现g的次数
#匹配oo
表示分组
() 分组
分组:() 将多个字符捆绑在一起,当作一个整体处理,如:\(root\)+
后向引用:\1, \2, ...
| 或者
a|b #a或b
C|cat #C或cat
(C|c)at #Cat或cat
看了扩展正则表达式是不是可以忘记普通正则表达式了,还是扩展正则表达式简单一点
grep
grep [选项]… 查找条件 目标文件
-
-i:查找时忽略大小写
-
-v:反向查找,输出与查找条件不相符的行
-
-o 只显示匹配项
-
-f 对比两个文件的相同行
-
-c 匹配的行数
egrep
egrep命令作用是在文件内查找指定的字符串。
egrep执行效果与grep -E相似,使用的语法及参数可参照grep指令,与grep的不同点在于解读字符串的方法。
egrep命令为 grep 的扩充版本, 改良了许多传统 grep 不能或不便的操作. 比方说:
grep之下不支持 ? 与 + 这两种modifier, 但egrep可以。
grep不支持 a|b 或 (abc|xyz) 这类”或一”比对, 但egrep可以。
grep在处理 {n,m} 时, 需用 \{ 与 \} 处理, 但egrep则不需要。
常用参数:
-i | 搜索时,忽略大小写 |
-c | 只输出匹配行的数量 |
-l | 只列出符合匹配的文件名,不列出具体的匹配行 |
-n | 列出所有的匹配行,显示行号 |
-h | 查询多文件时不显示文件名 |
-s | 不显示不存在、没有匹配文本的错误信息 |
-v | 显示不包含匹配文本的所有行 |
-w | 匹配整词 |
-x | 匹配整行 |
-r | 递归搜索 |
-q | 禁止输出任何结果,已退出状态表示搜索是否成功 |
-b | 打印匹配行距文件头部的偏移量,以字节为单位 |
-o | 与-b结合使用,打印匹配的词据文件头部的偏移量,以字节为单位 |
sed
sed 即 Stream EDitor,和 vi 不同,sed是行编辑器
Sed是从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行,直到最后一行。每当处理一行时,把当前处理的行存储在临时缓冲区中,称为模式空间(PatternSpace),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。一次处理一行的设计模式使得sed性能很高,sed在读取大文件时不会出现卡顿的现象。如果使用vi命令打开几十M上百M的文件,明显会出现有卡顿的现象,这是因为vi命令打开文件是一次性将文件加载到内存,然后再打开。Sed就避免了这种情况,一行一行的处理,打开速度非常快,执行速度也很快
基本用法
sed [option]... 'script;script;...' [input file...]
选项 自身脚本语法 支持标准输入管道
默认将输入结果输出,回车即可
[root@localhost data]#sed " "
aa
aa
aa
aa
vv
vv
b
b
ffgd
ffgd
查看文件内容,也支持重定向
sed脚本格式
'地址+命令'组成
1. 不给地址:对全文进行处理(比如行号)
2. 单地址:
#:指定的行,$:最后一行
/pattern/:被此处模式所能够匹配到的每一行
3. 地址范围:
#,# #从#行到第#行,3,6 从第3行到第6行
#,+# #从#行到+#行,3,+4 表示从3行到第7行
/pat1/,/pat2/ 第一个正则表达式和第二个正则表达式之间的行
#,/pat/ 从#号行为开始找到 pat为止
/pat/,# 找到#号个pat为止
4. 步进:~
1~2 奇数行
2~2 偶数行
命令
p | 打印当前模式空间内容,追加到默认输出之后 |
Ip | 忽略大小写输出 |
d | 删除模式空间匹配的行,并立即启用下一轮循环 |
a [\]text | 在指定行后面追加文本,支持使用\n实现多行追加 |
i [\]text | 在行前面插入文本 |
c [\]text | 替换行为单行或多行文本 |
w file | 保存模式匹配的行至指定文件 |
r file | 读取指定文件的文本至模式空间中匹配到的行后 |
= | 为模式空间中的行打印行号 |
! | 模式空间中匹配行取反处理 |
q | 结束或退出sed |
sed自带打印功能,比如10排序,p又打印一边
[root@localhost data]#seq 10 |sed 'p'
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10#-n关闭打印功能
[root@localhost data]#seq 10 |sed -n 'p'
1
2
3
4
5
6
7
8
9
10#直接显示第二行内容
[root@localhost data]#ifconfig ens33 |sed -n '2p'
inet 192.168.37.102 netmask 255.255.255.0 broadcast 192.168.37.255#还可以截取第几行到第几行
[root@localhost data]#cat xiao.txt |sed -n '3,6p'
\jji
kl
#3往后加6行[root@localhost data]#cat xiao.txt |sed -n '3,+6p'
\jji
kl
love
#奇数偶数表示[root@localhost data]#seq 10 |sed -n '1~2p'
1
3
5
7
9
[root@localhost data]#seq 10 |sed -n '0~2p'
2
4
6
8
10
#d选项删除[root@localhost data]#seq 10 |sed '3d'
1
2
4
5
6
7
8
9
10
[root@localhost data]#seq 10 |sed '3,5d'
1
2
6
7
8
9
10
#还可以直接替换,c,a是追加[root@localhost data]#seq 10 |sed '2ccc'
1
cc
3
4
5
6
7
8
9
10[root@localhost data]#seq 10 |sed '2aa'
1
2
a
3
4
5
6
7
8
9
10
sed常用命令
参数说明:
-e<script>或--expression=<script> | 以选项中指定的script来处理输入的文本文件。 |
-f<script文件>或--file=<script文件> | 以选项中指定的script文件来处理输入的文本文件。 |
-h或--help 显示帮助。 | |
-n或--quiet或--silent 仅显示script处理后的结果。 | |
-V或--version 显示版本信息。 |
动作说明:
a | 新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~ |
c | 取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行! |
d | 删除,所以 d 后面通常不接任何东西; |
i | 插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行); |
p | 打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~ |
s | 取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!用法 s/old/new/g |
w | /PATH/FILE 将替换成功的行保存至文件中 |
例如替换,将root替换为admin
[root@localhost data]#sed 's/root/admin/g' /etc/passwd |head
#替换文本字符
[root@localhost data]#cat xiao.txt
123
345
678
890
895
[root@localhost data]#sed -i -e 's/123/cba/' xiao.txt
[root@localhost data]#cat xiao.txt
cba
345
678
890
895
awk
awk:Aho, Weinberger, Kernighan,报告生成器,格式化文本输出,GNU/Linux发布的AWK目前由自
由软件基金会(FSF)进行开发和维护,通常也称它为 GNU AWK
工作原理
前面提到 sed 命令常用于一整行的处理,而 awk 比较倾向于将一行分成多个“字段”然后再进行处理,且默认情况下字段的分隔符为空格或 tab 键。awk 执行结果可以通过 print 的功能将字段数据打印显示。
格式
awk [选项] ‘模式条件{操作}’ 文件1 文件2....
awk -f|-v 脚本文件 文件1 文件2.....模式:
未指定表示 为空/1/2/代表正则表达式
关系表达式
基础用法
常用命令
-F | 指定输入时用到的字段分隔符 |
-v | 自定义变量 |
-f | 从脚本中读取awk命令 |
-m | 对val值设置内在限制 |
和sed一样都可以打印一遍
[root@localhost data]#awk '{print}'
12
12
45
45
lve
lve
love
love
[root@localhost data]#awk '{print "hello"}'#字符串需要添加双引号,单引号已被使用,数字不需要
1
hello
1
hello
2
hello
3
hello
4
hello#BEGIN比较特殊值打一行
[root@localhost data]#awk 'BEGIN {print "hello"}'
hello
#指定冒号作为分隔符,打印第一列和第三列[root@localhost data]#cat /etc/passwd|awk -F: '{print $1,$3}'|head
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
operator 11
查看磁盘已用空间
[root@localhost data]#df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mapper/centos-root 39044480 5681088 33363392 15% /
devtmpfs 1916728 0 1916728 0% /dev
tmpfs 1932652 0 1932652 0% /dev/shm
tmpfs 1932652 17452 1915200 1% /run
tmpfs 1932652 0 1932652 0% /sys/fs/cgroup
/dev/sda1 19520512 182412 19338100 1% /boot
tmpfs 386532 44 386488 1% /run/user/0
/dev/sr0 4414592 4414592 0 100% /run/media/root/CentOS 7 x86_64
/dev/sdb 20961280 32944 20928336 1% /mnt
[root@localhost data]#df|awk -F"( +|%)" '{print $5}'
Use
15
0
0
1
0
1
1
100
1
结合sed取IP地址
[root@localhost data]#ifconfig ens33 |sed -n '2p' |awk '{print $2}'
192.168.37.102
[root@localhost data]#ifconfig ens33 |awk /netmask/'{print $2}'
192.168.37.102
#$0代表全部元素
[root@localhost data]#awk -F: '{print $0}' /etc/passwd
#$1代表第一列
[root@localhost data]#awk -F: '{print $1}' /etc/passwd
#已root为开头的行
[root@localhost data]#awk '/^root/{print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
#统计当前已/bin/bash结尾的行
[root@localhost data]#grep -c "/bin/bash$" /etc/passwd
2
# BEGIN{}模式表示,在处理指定的文本前,需要先执行BEGIN模式中的指定动作; awk再处理指定的文本,之后再执行END模式中的指定动作,END{}语句中,一般会放入打印结果等语句。
一共查找了42次
[root@localhost data]#awk 'BEGIN {x=0};/\/bin\/bash$/;{x++};END{print x}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
xiaobin:x:1000:1000:xiaobin:/home/xiaobin:/bin/bash
42
awk的内置变量
FS | 指定每行文本的字段分隔符,缺省为空格或制表位。与 “-F”作用相同 -v "FS=:" |
NF | 当前处理的行的字段个数 |
NR | 当前处理的行的行号(序数) |
$0 | 当前处理的行的整行内容 |
$n | 当前处理行的第n个字段(第n列) |
FILENAME | 被处理的文件名 |
RS | 行分隔符。awk从文件上读取资料时,将根据RS的定义就把资料切割成许多条记录,而awk一次仅读入一条记录进行处理。预设值是\n |
FS
[root@localhost data]#awk -v FS=: '{print $1FS$3}' /etc/passwd
#此处FS 相当于于变量
两者相同
[root@localhost data]#awk -F: '{print $1":"$3}' /etc/passwd
NF
[root@localhost data]#awk -F: '{print NF}' /etc/passwd
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
[root@localhost data]#awk -F: '{print $NF}' /etc/passwd匹配最后一个字段
#倒数第二行
[root@localhost data]#df|awk -F "[ %]+" '{print $(NF-1)}'
Mounted
15
0
0
1
0
1
1
7
1
NR
#行号
[root@localhost data]#awk '{print NR,$1}' /etc/passwd
#只取第三行第一个字符
[root@localhost data]#awk 'NR==3{print $1}' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
#取行间 大于5小于10[root@localhost data]#seq 10|awk 'NR>5 && NR<10'
6
7
8
9
最后一道面试题
统计/etc/fstab文件中每个单词出现的次数
[root@localhost data]#grep -Eo "\b[[:alpha:]]+\b" /etc/fstab |sort |uniq -c
1 Accessible
1 anaconda
1 and
1 are
1 blkid
1 boot
2 by
2 centos
1 Created
3 defaults
3 dev
1 disk
1 etc
1 filesystems
1 findfs
1 for
2 fstab
1 info
1 maintained
1 man
2 mapper
1 more
1 mount
1 Oct
1 on
1 or
1 pages
1 reference
1 root
1 See
3 swap
1 Thu
1 under
1 UUID
2 xfs