Linux进阶之正则,shell三剑客(grep,awk,sed),cut,sort,uniq
一、正则表达式:Regular Expression
正则表达式:正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。
作用:用一些特殊的字符来描述一个模式
正则是用于对文件中的内容进行过滤和匹配
通配符用于对文件名进行匹配
注意:在匹配模式中一定要加上引号
二、符号:
^ 以开头
$ 以结尾
^12$ 以1开头以2结尾
^$ 空行
. 表示任意的一位字符(数字、字母、符号)
+ 表示其前面的字符至少重复一次,可以是无数次
? 表示其前面的字符出现最多一次的情况,可以是0次
* 重复任意次数(包括0次)
.* 表示任意长度的任意字符
{}
{数字} 重复数字次,准确的重复多少次
{数字1,数字2} 至少重复数字1次,最多重复数字2次
{数字,} 至少重复数字次,最多不限
{,数字} 最多重复数字次,最少不限
[] 表示范围,多个范围使用 , 分隔
[^字符] 表示匹配[^字符]之外的任意一个字符
^[^] 匹配不是中括号内任意一个字符开头的行
[0-9] 表示1位数字(0-9任意数字)
[a-z] 表示1位小写字母
[A-Z] 表示1位大写字母
[0-9,a-z,A-Z]
() 表示内部是一个整体
| 表示或者
三、常用的正则表达式
1、车牌号码
^[A-Z][0-9,A-Z]{5}$
2、手机号码
^1[0-9]{10}$
3、身份证号
^[0-9]{17}[0-9,X]$
4、IP(0-255.0-255.0-255.0-255)
0-9 [0-9]
10-99 [1-9][0-9]
100-199 1[0-9][0-9]
200-249 2[0-4][0-9]
250-255 25[0-5]
方法一:^([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$
方法二:^([0-9]\.|[1-9][0-9]\.|1[0-9][0-9]\.|2[0-4][0-9]\.|25[0-5]\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$
5、密码(8位以上,包含数字、大小写字母)
egrep [a-z] passwd | egrep [A-Z] | egrep [0-9] | egrep ^.{8,}$
四、grep
作用:用于对文件中的内容进行过滤
原理:逐行对文件中的内容根据样式进行匹配,如果匹配成功就过滤出该行
格式:grep [options] PATTERN file
PATTERN:要匹配的模式
参数:
-e =正则 用正则表达式来进行匹配操作,egrep=grep -E(extended-regexp)用grep调用正则表达式
-f =文件 从文件中取得条件
-i (--ignore-case)忽略文件中内容的大小写
-n (--line-number)打印包含匹配项的行和行号
-o (--only-matching)只输出匹配的选项(不显示整行)
-w 完全匹配字词(精确匹配)
-x 仅完全匹配一行
-c (--count)只打印每个文件匹配的行数
-v (--invert-match)取反,打印不匹配的行
-V 显示版本信息
--color 将匹配到的内容进行着色
--help 显示帮助
-B NUM (--before-context=NUM) 显示匹配到的条件的之前 数字 行
-A NUM (--sfter-context=NUM) 显示匹配到的条件的之后 数字 行
-C NUM (--context=NUM)显示匹配到的条件的为中心上下 数字 行
-NUM 等于-C
例子:
1、显示出test中不包含字母c的行
[root@ren4 ~]# grep -v "c" test
2、统计test中包含字母a的行的数量
[root@ren4 ~]# grep "a" test | wc -l
3、过滤出包含大写字母的行
[root@ren4 ~]# grep '[A-Z]' test
4、匹配非数字字符
[root@ren4 ~]# grep '[^0-9]' test
5、查看包含字母a的行,要求显示该行上下各2行
[root@ren4 ~]# grep --color -C 2 'a' test
6、过滤出一行中a在前,v在后的行
[root@ren4 ~]# grep --color 'a.*v' test
7、匹配a和b之间有最少2个c最多5个c的行
[root@ren4 ~]# grep "ac\{2,5\}b" test
accccb
[root@ren4 ~]# egrep "ac{2,5}b" test
accccb
8过滤出以#为开头,且第二个字符是空格的行
[root@ren4 ~]# grep "^#[[:space:]]" test
[root@ren4 ~]# grep "^#[:space:]" test #语法错误
grep: 字符类的语法是 [[:space:]],而非 [:space:]
9过滤出行首和行尾字母相同的行
[root@ren4 ~]# grep "^\([a-z]\).*\1$" test
adfdfa
[root@ren4 ~]# egrep "^([a-z]).*\1$" test
adfdfa
10、过滤出第一个字符是#,且第二个字符串是非空字符,而且结尾是数字的行
[root@ren4 ~]# grep --color "^#[^[:space:]].*[0-9]$" test
正则练习:
使用文件 /etc/init.d/functions ,下面可能有些部分题目匹配不到符合的情况。
1. 过滤出包含大写字母的行
[root@ren4 ~]# egrep "[A-Z]" /etc/init.d/functions
2. 匹配非数字字符
[root@ren4 ~]# egrep "[^0-9]" /etc/init.d/functions
3. 过滤出一行中a在前,b在后的行
[root@ren4 ~]# egrep "a.*b" /etc/init.d/functions
4. 匹配a和b之间有最少2个c最多5个c的行
[root@ren4 ~]# egrep "ac{2,5]b" /etc/init.d/functions
5. 过滤出一行包含相同数字的行/etc/init.d/functions
[root@ren4 ~]# egrep ".*([0-9]).*\1" /etc/init.d/functions
6. 过滤出不是(空行和以#开头)的行
[root@ren5 ~]# egrep -v "(^#)|(^$)" test
五、awk
1、功能:逐行处理文件中的内容(读取一行,处理一行)
2、语法:
awk [options] '[pattern]{action}' fileName
options:选项,比如 -F 指定分隔符
pattern:输出的条件,比如仅仅输出以#开头的行
action:按照选项切换,并且是符合条件的行,要执行的操作或者命令,比如输出
awk -F分隔符号 '{print $列数}' #-F可以不写,默认使用空格分隔
awk -F分隔符 '{print $列数}' 文件名 #可以直接过滤文件,但不会对源文件内容进行更改
#列说明 $0所有列 $数字 第数字列
3、概念及参数
记录(record):一行就是一个记录
分隔符(field separator):进行对记录进行切割的时候所使用的字符
字段(field):将一条记录分割成的每一段
FILENAME:当前处理文件的文件名
FS(Field Separator):字段分隔符(默认是以空格为分隔符=)
NR(Number of Rrecord):记录的编号(awk每读取一行,NR就加1==)
NF(Number of Field):字段数量(记录了当前这条记录包含多少个字段==)
ORS(Output Record Separator):指定输出记录分隔符(指定在输出结果中记录末尾是什么,默认是\n,也就是换行)
OFS(Output Field Separator):输出字段分隔符
RS:记录分隔符
4、示例:
1.用 awk 打印所有包含有 root 字段的行
[root@ren5 ~]# awk '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
2.查看 df -h 命令的第 2 列
[root@ren5 ~]# df -h |awk '{print $2}'
3. 查看 df -h 命令的第 2,5 列
[root@ren5 ~]# df -h |awk '{print $2,$5}'
4.显示 passwd 的第四行
[root@ren5 ~]# awk 'NR==4' /etc/passwd #必须是两个等号
5.打印 ls –l / 中包含 etc字段行的第二区域
[root@ren5 ~]# ls -l / |awk '/etc/ {print $2}'
6.列示月份及年份 (\n 为换行符 )
[root@ren5 ~]# date |awk '{print $1,$2}'
2019年 08月
[root@ren5 ~]# date |awk '{print "Year:"$1"\nMonth:"$2}'
Year:2019年
Month:08月
7.在有 root 关键字的行的第 1 列后面增加 1 个 \t制表符,并增
加 RedHat,第 2 列后面加 ! 字符
awk -F: '/root/{print $1 "\tRedHat" $2 "!"}' /etc/passwd
8.在有 root字段的行前增加记录号 ($0 为行头前 )
[root@ren5 ~]# awk -F: '/root/{print NR,$0}' /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
10 operator:x:11:0:operator:/root:/sbin/nologin
[root@ren5 ~]# awk -F: '/root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
9.以:分割,匹配第一列的 root字段,如果有,则显示整行
[root@ren5 ~]# awk -F ":" '$1 ~/root/' /etc/passwd
10.以:分割,匹配第一列不存在 root字段的行,如果有,则显
示行号和第一列
[root@ren5 ~]# awk -F ":" '$1 !~/root/{print NR,$1}' /etc/passwd
11. 在结果前打印 hello,可以是任何的字符
[root@ren5 ~]# awk 'BEGIN{print "Hello"}{print $0}' /etc/passwd
12. 在结果后打印 hello,可以是任何的字符
[root@ren5 ~]# awk 'END{print "Hello"}{print $0}' /etc/passwd
13.使用awk进行计算 +加 -减 *乘 /除 可以带()^开方
[root@ren5 ~]# awk 'BEGIN{print 2+1}' /etc/passwd
14.比较 >大于 <小于 >=大于等于 <=小于等于 ==等于
[root@ren5 ~]# awk -F ':' '$3<=88{print $1,$3}' /etc/passwd
#如果第三列小于等于88,输出第一列和第三列
六、sed
1、概念:文本编辑器,也是对文件中的内容进行逐行的处理(一次处理一行)
2、功能:通过指定的正则表达式完成指定关键字的过滤、截取、修改等操作
3、sed的工作原理:
sed读取一行,首先将这行放入到缓存中
然后,才对这行进行处理
处理完成以后,将缓冲区的内容发送到终端
存储sed读取到的内容的缓存区空间称之为:模式空间(Pattern Space)
4、语法格式: sed ‘command’ filename(s)
5、特点:
1.sed属于一个流线式的非交互式的编辑器
2. sed在输入命令和文件名后,将在屏幕上输出
3.在不用重定向至文件之前,是不会改变文件现有内容。以避免修改文件时出现问题
6、选项:
Option选项 |
解释说明 |
-n(no) |
取消默认的sed软件的输出,常与sed命令的p连用。(抑制内存输出) |
-e(entry) |
一行命令语句可以执行多条sed命令 |
-r(regular) |
使用扩展正则表达式,默认情况sed只识别基本正则表达式 |
-i(inside) |
直接修改文件内容,而不是输出到终端,如果不使用-i选项sed软件只是修改在内存中的数据,并不会影响磁盘上的文件 |
p(print) |
打印模式空间内容,通常p会与选项-n一起使用 |
a(append) |
追加,在指定行后添加一行或多行文本 |
i(insert) |
插入,在指定行前添加一行或多行文本 |
d(delete) |
删除指定的行 |
c(change) |
取代指定的行 |
s(substitute) |
字符串替换 |
r(read) |
从一个文件中读取到另一个文件中 |
w(write) |
从一个文件中将匹配的内容写入到另外一个文件中 |
& |
引用前面的搜索结果 |
! |
对指定行以外的所有行应用命令,对命令的执行结果取反(不显示命令找到的内容) |
6、示例:
(1)查找指定的字符串
[root@ren5 ~]# sed -n '/root/p' /etc/passwd #显示有/root/的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@ren5 ~]# sed -n '2,5p' /etc/passwd #显示2到5行
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@ren5 ~]# sed -n '2p' /etc/passwd #显示第2 行的内容,如果不加-n,是显示所有内容,但第二行有2行。
(2)删除
[root@ren5 ~]# sed 'd' test #删除所有test内的内容
[root@ren5 ~]# sed '2d' test #删除第2行
[root@ren5 ~]# sed '2,5d' test #删除第2到5行
[root@ren5 ~]# sed '/ren/d' test #删除包含ren的行
[root@ren5 ~]# sed '2,$d' test #删除第2行到行尾的内容(包含第2行)
[root@ren5 ~]# sed '2,6!d' test #(取反删除)除了第2行到第6行,其它都删除
[root@ren5 ~]# sed '/ren/!d' test #删除不包含ren的所有行
(3)增加内容
[root@ren5 ~]# sed "2a 你好" test #在第2行后增加内容
this is the first line
this is the second line
你好
this is the third line
this is the forth line
[root@ren5 ~]# sed "2i 你好" test #在第2行前增加内容
this is the first line
你好
this is the second line
this is the third line
[root@ren5 ~]# sed "i 你好" test #在每一行的前面增加
[root@ren5 ~]# sed "2,5i 你好" test #在2-5行前面增加
[root@ren5 ~]# sed "2i 你好\n我很好" test #换行(增加多行内容)
this is the first line
你好
我很好
this is the second line
[root@ren5 ~]# sed "2i 你好\n\t\t我很好" test #换行+tab+tab
this is the first line
你好
我很好
this is the second line
(4)修改,替换
[root@ren5 ~]# sed '2c 改过之后的第二行' test #整行替换
this is the first line
改过之后的第二行
this is the third line
[root@ren5 ~]# sed 's/is/ese/' test #默认替换每一行的第一个
these is the first line
[root@ren5 ~]# sed 's/is/ese/g' test #全文替换
these ese the first line
[root@ren5 ~]# sed 'y/e/E/' test #字母替换,默认替换所有适配字母
this is thE first line
[root@ren5 ~]# sed -i 's/t/T/' test #修改磁盘文件
[root@ren5 ~]# cat test
This is the first line
[root@ren5 ~]# sed 's/is/are/2' test #指定替换每行的第2个词
This are the first line
[root@ren5 ~]# sed 's/is/are/2w test2' test #将修改后的文本保存至test2
(5)多点编辑(-e)
[root@ren5 ~]# sed -e '2d' -e '4d' test #删除第2行和第4行
This is the first line
This is the third line
This is the fivth line
[root@ren5 ~]# sed -n -e '3p' -e '7p' test #显示第3行和点7行
This is the third line
This is the seventh line
[root@ren5 ~]# sed -e '/^#/d' -e '/^$/d' test #删除文件中的注释行和空白行
七、其它小命令(cut,sort,uniq)
1、cut命令
作用:根据指定的分隔符来切割数据,然后显示指定的部分
选项:
-d ’字符’ :(--delimiter=分界符)指定分隔符
-f #:(--fields=LIST)指定显示分割后的那一部分数据,取第几位的字符(#代表数字)
输出的情况
1)输出一段:指定一个编号 2
2)输出连续多段:编号-编号 2-5
3)输出不连续多段:编号,编号... 2,3,5
示例:
(1)bin:10:15:i am bin:/home/bin:/sbin/nologin
#输出上面的15
[root@ren5 ~]# echo "bin:10:15:i am bin:/home/bin:/sbin/nologin" |cut -d ':' -f3
15
(2)#输出系统中全部用户的用户名和shell类型
[root@ren5 ~]# cat /etc/passwd |cut -d":" -f1,7
root:/bin/bash
2、sort命令
作用:按字符进行比较和排序,默认以排序 ASCII 方式进行排序 [a-z]
格式:sort 选项 file
选项:
-t:( --field-separator=分隔符)指定分隔符
-k:(--key=KEYDEF)根据切割后的那一段进行排序(根据切割后的那一段排序,不是取出来那一段)
-n:(--numeric-sort)表示根据数字进行排序(默认是根据字符进行排序)
-f:(--ignore-case)忽略要比较的字符大小写
-c, --check, --check=diagnose-first 检查输入是否已排序,若已有序则不进行操作
-u:(--unique)去除重复的行(只要那个指定的字段重复,就认定是重复的行)配合-c,严格校验排序;不配合-c,则只输出一次排序
-r:(--reverse)按照降序(逆序)排序[z-a]
示例:
(1)对 /etc/passwd 文件进行升序排序
[root@ren5 ~]# sort /etc/passwd
(2)对 /etc/passwd 文件进行降序排序
[root@ren5 ~]# sort -r /etc/passwd
(3)对 /etc/passwd 第3列进行数值排序,分界符为:
[root@ren5 ~]# sort -n -k 3 -t : /etc/passwd
(4)对第 1 列的第2个字符开始至本列最后1个字符排序
[root@ren5 ~]# sort -k 1.2 -t : /etc/passwd #注意1.2中间是小数点
3、uniq命令
uniq命令(通常结合sort先进行排序,然后再使用该命令统计相同的行出现的次数)
作用:去除重复的行(相邻且相同,认定为重复)
选项:
-c:(--count)在行首用数字表示该行出现了多少次
-d:(--repeated)仅仅显示出现过重复的行
-u:(--unique)仅仅显示那些没有出现重复过的行
例子:uniq用法
[root@ren5 ~]# uniq -c test
2 This is the first line
1 This is the third line
[root@ren5 ~]# uniq -d test
This is the first line
[root@ren5 ~]# uniq -u test
This is the third line
This is the forth line
[root@ren5 ~]# uniq test