文章目录
前言
参考视频:shell编程之正则表达式
参考网站:菜鸟教程
shell编程的变量笔记:shell编程之变量的笔记
想更深入了解sed命令和awk命令的可以观看这个视频:实例妙解Sed和Awk的秘密
一.正则表达式
1.正则表达式概述
正则表达式是用于描述字符排列和匹配模式的一种语法规则。它主要用于字符串的模式分割、匹配、查找以及替换操作。
2.正则表达式与通配符
(1)正则表达式与通配符
- 正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配,grep、awk、sed等命令可以支持正则表达式。
- 通配符用来匹配符合条件的文件名,通配符是完全匹配。ls、find、cp这些命令不支持正则表达式,所以只能使用shell自己的通配符来进行匹配
find命令可以加上“-regex”使用正则表达式;grep命令的正则表达式一定要用双引号或单引号括起来
(2)通配符
通配符 | 作用 |
---|---|
? | 匹配一个任意字符 |
* | 匹配0个或任意多个任意字符,也就是可以匹配任意内容 |
[] | 匹配中括号中任意一个字符。例如:[abc]代表一定匹配一个字符,或者是a,或者是b,或者是c 。 |
[-] | 匹配中括号中任意一个字符,-代表一个范围。例如[a-z]代表匹配一个小写字母。 |
[^] | 逻辑非,表示匹配不是中括号内的一个字符。例如:[^0-9]代表匹配一个不是数字的字符 |
3.正则表达式
(1)基础正则表达式图
正则表达式分为基础正则表达式和扩展表达式,这里只是基础正则表达式
(2)“*”前一个字符匹配0次或任意多次
“a*”
#匹配所有内容,包含空白行
“aa*”
#匹配至少包含一个a的行
“aaa*”
#匹配最少包含两个连续a的字符串
(3)“.”匹配除了换行符外任意一个字符
“s..d”
#匹配在s和d这两个字母之间一定有两个字符的字符串
“s.d”
#匹配在s和d字母之间有任意字符
“.*”
#匹配所有内容
(3)“^”匹配行首,“$”匹配行尾
“^M”
#匹配以“M”开头的行
“n$”
#匹配以“n”结尾的行
“^$”
#会匹配空白行(具体怎么体现,可以设置显示行号)
例子:
[root@Test ~]# grep -n "^$" anaconda-ks.cfg
15:
19:
31:
39:
41:
43:
45:
(4)“[]”匹配中括号中指定的任意一个字符,只匹配一个字符
“s[ao]d”
#匹配s和d字母中,要不是a,要不是o
"[0-9]"
#匹配任意一个数字
“^[a-z]”
#匹配小写字母开头的行
(5)“[^]”匹配除中括号的字符以外的任意一个字符
“^[^a-z]”
#匹配不是小写字母开头的行
“^[^a-zA-Z]”
#匹配不是字母开头的行;注:linux不能这么写 “^[^A-z]”,其它语言可以
例子:
[root@Test ~]# grep "^[^A-z]" anaconda-ks.cfg
grep: Invalid range end
(6)“\”转义符
“\.$”
#匹配使用“.”结尾的行
“\”的作用是使有特殊含义的字符失去特殊含义
(7)“{n}”表示其前面的字符恰好出现n次
“a\{3\}”
#匹配a字母连续出现3次的字符串;
“[0-9]\{3\}”
#匹配包含连续的3个数字的字符创
注意:正则表达式是包含匹配;用“\”使特殊含义的字符失去特殊含义
(8)“{n,}”表示其前面的字符出现不少于n次
“^[0-9]\{3,\}”
#匹配最少连续3个数字开头的行
(9)“{n,m}”表示其前面的字符至少出现n次,最多出现m次
“sa\{1,3\}i”
#匹配在字母s和字母i之间有最少1个a,最多3个a
4.例子
“[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}”
#匹配日期格式为YYYY-MM-DD
“[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}”
#匹配ip地址
二.字符截取命令
1.提取字符串命令:cut命令
(1)格式
cut [选项] 文件名
选项:
-f 列号:提取第几列
-d 分隔符:按照指定分隔符分割列
(2)例子
#分割符为“:”,提取第1列和第2列
[root@Test etc]# cut -d ":" -f 1,2 passwd
root:x
bin:x
daemon:x
adm:x
lp:x
sync:x
shutdown:x
halt:x
mail:x
operator:x
games:x
ftp:x
nobody:x
systemd-network:x
dbus:x
polkitd:x
libstoragemgmt:x
abrt:x
rpc:x
apache:x
sshd:x
postfix:x
ntp:x
chrony:x
tcpdump:x
vboxadd:x
-f选项使用","表示多个指定的列,使用“-”表示列数范围
(3)局限性
分隔符不能是空格
2.格式化输出命令:printf命令
(1)命令格式
printf [format] [文本1] [文本2] ..
常用格式替换符
格式替换符 | 作用 |
---|---|
%s | 字符串 |
%f | 浮点格式 |
%c | ASCII字符,即显示对应参数的第一个字符 |
%d,%i | 十进制整数 |
%o | 八进制值 |
%u | 不带正负号的十进制值 |
%x | 十六进制值(a-f) |
%X | 十六进制值(A-F) |
%% | 表示%本身 |
%ns:输出字符串,n代表输出几个字符
%ni:输出整数,n代表输出几个数字
%m.nf:输出浮点数,m和n是数字,指代输出的整数位数和小数位数
常用转义字符
转义字符 | 作用 |
---|---|
\a | 警告字符,通常为ASCII的BEL字符 |
\b | 后退 |
\f | 换页 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ | 表示\本身 |
(2)例子
#会认为后面的都是字符串
[root@Test ~]# printf %s 1 2 3 4 5 6
#会认为除了第一个“%s”后面的都是字符串
[root@Test ~]# printf %s %s %s 1 2 3 4 5 6
#会认为先输出3个,再输出3个
[root@Test ~]# printf '%s %s %s' 1 2 3 4 5 6
#会认为先输出3个,再输出3个,"\n"表示换行
[root@Test ~]# printf '%s %s %s\n' 1 2 3 4 5 6
#输出文件内容,如果需要格式输出就加上对应调整格式的转义字符
[root@Test ~]# printf '%s' $(cat anaconda-ks.cfg)
printf不支持输出流;最好加上单引号
(3)在awk命令的输出中支持print和printf命令
- print:print会在每个输出之后自动加入一个换行符(Linux默认没有print命令)
- printf:printf是标准格式输出命令,并不会自动加入换行符,如果需要换行,需要手工加入换行符
3.awk命令(上)
(1)格式
awk '条件1{动作1}条件2{动作2}...'文件名
条件:
一般使用关系表达式作为条件
x > 10 判断变量x是否大于10
动作:
格式化输出
流程控制语句
[root@Test ~]# df -h | awk '{print $1 "\t" $3}'
文件系统 已用
/dev/sda3 1.7G
devtmpfs 0
tmpfs 0
tmpfs 8.7M
tmpfs 0
/dev/sda1 143M
www 133G
tmpfs 0
[root@Test ~]#
动作必须使用花括号括起来;转义符必须使用双引号括起来;只能用单引号
4.awk命令(下)
(1)获取/dev/sda3分区的使用率
[root@Test ~]# df -h
文件系统 容量 已用 可用 已用% 挂载点
/dev/sda3 17G 1.7G 16G 10% /
devtmpfs 909M 0 909M 0% /dev
tmpfs 919M 0 919M 0% /dev/shm
tmpfs 919M 8.7M 911M 1% /run
tmpfs 919M 0 919M 0% /sys/fs/cgroup
/dev/sda1 1014M 143M 872M 15% /boot
www 183G 133G 51G 73% /var/www
tmpfs 184M 0 184M 0% /run/user/0
[root@Test ~]# df -h | grep "/dev/sda3" | awk '{print $5}' |cut -d "%" -f 1
10
(2)BEGIN
BEGIN{ 这里面放的是执行前的语句 }
[root@Test ~]# df -h | grep "/dev/sda3" | awk 'BEGIN{print "我是begin"}{print $5}'
我是begin
10%
BEGIN表示在所有动作之前,满足这个条件则执行它后面的动作
(3)END
END {这里面放的是处理完所有的行后要执行的语句 }
[root@Test ~]# df -h | grep "/dev/sda3" | awk 'END{print "我是end"}{print $5}'
10%
我是end
END表示在所有动作之后,满足这个条件则执行它后面的动作
(4)内置变量
内置变量图
例子
[root@Test ~]# cat /etc/passwd |grep "/bin/bash" |awk 'BEGIN{FS=":"}{printf $1 "\t" $3 "\n"}'
root 0
(5)关系运算符
关系运算符图
例子
[root@Test ~]# df -h |cut -d "%" -f 1
文件系统 容量 已用 可用 已用
/dev/sda3 17G 1.7G 16G 10
devtmpfs 909M 0 909M 0
tmpfs 919M 0 919M 0
tmpfs 919M 8.7M 911M 1
tmpfs 919M 0 919M 0
/dev/sda1 1014M 143M 872M 15
www 183G 133G 51G 73
[root@Test ~]# df -h | awk '{print $5}' |cut -d "%" -f 1 | grep -v "已用"|awk '$1 >=10{printf $1 "\n"}'
10
15
73
5.sed命令(上)
(1)sed命令的概述
sed命令是一种几乎包括在所有UNIX平台(包括Linux)的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。
(2)sed命令格式
sed [选项] ‘[动作]’ 文件名
选项:
-n : 一般sed命令会把所以数据都输出到屏幕,如果加入此选项则只会把经sed命令处理的行输出到屏幕
-e :允许对输入数据应用多条sed命令编辑
-i :用sed命令的修改结果直接修改读取数据的文件,而不是由屏幕输出
动作:
a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!
[root@Test test]# cat test.txt
2020-01-01
sadasdasd
114.114.114.114
192.168.0.111
#动作'2p'表示打印第2行,sed把它打印出来了,但由于没有加'-n'的选项,因此把原文件数据也打印了一遍,便多出来了一行
[root@Test test]# sed '2p' test.txt
2020-01-01
sadasdasd
sadasdasd
114.114.114.114
192.168.0.111
#‘p’动作必须加上“-n“选项,才会得到你想要的结果
[root@Test test]# sed -n '2p' test.txt
sadasdasd
注:动作必须使用单引号括起来
6.sed命令(下)
(1)删除的例子
[root@Test test]# cat test.txt
2020-01-01
sadasdasd
114.114.114.114
192.168.0.111
#表示删除第2行
[root@Test test]# sed "2d" test.txt
2020-01-01
114.114.114.114
192.168.0.111
#表示删除第2行到第4行
[root@Test test]# sed "2,4d" test.txt
2020-01-01
192.168.0.111
(2)追加和插入的例子
#第2行追加
[root@Test test]# sed '2a testaaaaa' test.txt
2020-01-01
sadasdasd
testaaaaa
114.114.114.114
192.168.0.111
#第2行插入
[root@Test test]# sed '2i testaaaaa' test.txt
2020-01-01
testaaaaa
sadasdasd
114.114.114.114
192.168.0.111
[root@Test test]#
(3)数据替换的例子
[root@Test test]# sed '2c replace' test.txt
2020-01-01
replace
114.114.114.114
192.168.0.111
注意:这是整行替换
(4)字符串替换的例子
格式
sed 's/旧字符串/新字符串/g' 文件名
例子
#‘g’表示有多少个就替换多少个,'s'前面的4表示第几行
[root@Test test]# sed '4s/114/110/g' test.txt
2020-01-01
sadasdasd
110.110.110.110
192.168.0.111
如果加上“-i”选项则会修改文件里的原始数据,小心使用
(5)多个动作的例子
[root@Test test]# sed -e '4s/114/110/g;1s/2020/2019/g' test.txt
2019-01-01
sadasdasd
110.110.110.110
192.168.0.111
三.字符处理命令
1.排序命令:sort命令
(1)格式
sort [选项] 文件名
选项:
-f :忽略大小写
-n :以数值型排序,默认使用字符串型排序
-r :反向排序
-t :指定分隔符,默认是分隔符是制表符
-k n[,m] :按照指定的字段范围排序,从第n字段开始,m字段结束(默认是到行尾)
(2)例子
#排序用户信息文件
[root@Test test]# sort /etc/passwd
#反向排序
[root@Test test]# sort /etc/passwd
[root@Test test]# sort -t ":" -k 3,3 /etc/passwd
#按照数值排序,指定分隔符是“:”,用第三字段开头,第三字段结束排序,就是只用第三字段排序
[root@Test test]# sort -n -t ":" -k 3,3 /etc/passwd
注意:如果我们需要数字排序一定要加上“-n”选项
2.统计命令wc
(1)格式
wc [选项] 文件名
选项:
-l :只统计行数
-w : 只统计单词数
-m :只统计字符数
(2)例子
[root@centos7 ~]# wc -l anaconda-ks.cfg
49 anaconda-ks.cfg
#注意:wc然后enter,按ctrl+d可以结束
[root@centos7 ~]# wc
asdasdsa
sadasda
sadsad
asdsad
asdsad
5 5 38
命令<文件把文件作为命令的输入
命令<<标识符
......
标识符把标识符之间内容作为命令的输入
例如:
# <
[root@centos7 ~]# wc < anaconda-ks.cfg
49 123 1278
#<< 标识符,遇到该标识符才结束
[root@centos7 ~]# wc << wcd
> asdasd
> asdsad
> asdsad
> asdsad
> wcd
4 4 28
3.检查及删除文本文件中重复出现的行列:uniq 命令
(1)格式
uniq [选项] 文件
选项:
-c : 在每列旁边显示该行重复出现的次数
-d : 仅显示重复出现的行列
-f<栏位> :忽略比较指定的栏位
-s<字符位置> :忽略比较指定的字符
-u :仅显示出一次的行列
-w<字符位置> : 指定要比较的字符
(2)例子
[root@Test test]# uniq -c test.txt
1 2020-01-01
1 sadasdasd
1
1 114.114.114.114
1 192.168.0.111