菜单
本页目录

17 shell高级

一 正则表达式

1 概念

grep、awk、sed				采用正则表达式(在文件内容中查找)

ls、find、cp					采用通配符(在文件名中查找)

2 基础正则表达式

元字符作用
.出换行符意外,任意一个字符
*前一个字符0次或者任意多次 .* 表示除换行外,任意字符0次或者多次
^匹配行首 "^root" 表示以root开头
$匹配行尾 "/bin/bash$" 表示以/bin/bash结尾
[ ]任意一个字符,中括号中的其中一个 [0-9] 表示0到9其中一个 [a-z] 表示a到z其中一个
[^]反选 [ ^1-2 ]排除1到2中任意一个
\取消特殊含义
\ {n \ }前一个字符出现n次则列出
\ {n, \ }前一个字符至少出现n次
\ {n,m \ }前一个字符至少出现n次,最多出现m次
#练习:过滤电话号码
[root@localhost ~]# cat /root/number.txt 
11111111111
12312343432
1231231242344
09123812388
123242325
13666386291
11a11111111
q3666386291
1366638629g

#练习:过滤电话号码 
[root@localhost ~]# grep "^1[0-9]\{10\}$" /root/number.txt 
11111111111
12312343432
13666386291
	
#练习:过滤邮箱		
#此处邮箱规则:只能字母数字开头    开头第二个到@前第二个字符只能出现数字、字母、-、_	  @前一个字符只能为字母或数字   @后面为qq时,@前面只能为数字		
#@后面为其他时,可以为字母或数字     以.com结尾     @前字符个数在4到16之间
[root@localhost ~]# cat  ./mail.txt 
hubo@xxhf.com
hb@xxhf.com
huboixxhf.com
_abc@163.com
123_@163.com
213_123@.com
&^%$#@*(4583@qq.com
hubo_aa@163.com
458340667@qq.com
458340667@@qq.com
458340667@qq.com*
458340667@qq.com.com1.cn
458340667@qq.com.net.a
4583123123312321321321332123121332123123121321340667@qq.com
458a40667@qq.com
q5834066q@qq.com
hubo#ixxhf.com
1a2sd3ad4f-asd_1@xxhf.com
1a2sd4f-asd_1@xxhf.com
yqyqyq@xxhf.com
yq@xxhf.com
Yqyqyq@xxhf.com
[root@localhost ~]# egrep "((^([1-9]|[a-z]|[A-Z])([a-z]|[0-9]|-|_){1,13}([a-z]|[0-9])@(([1-9]|[a-p]|[r-z]).*\.com$))|^([0-9]{1,15}@qq.com$))" /root/mail.txt
hubo@xxhf.com
hubo_aa@163.com
458340667@qq.com
1a2sd4f-asd_1@xxhf.com
yqyqyq@xxhf.com
Yqyqyq@xxhf.com


精确查找:

\ <符号和\ >符号			界定左右边界
[root@localhost ~]# echo "hello" |grep "\<hello\>"
hello
[root@localhost ~]# echo "bbbhelloaa" |grep "\<hello\>"

3 扩展正则表达式 egrep

​ 不能被grep使用,需要用egrep

扩展元字符作用
+匹配前一个字符出现1次或多次 roo*=ro+
?匹配前一个字符出现0次或1次
|可以是管道符前面的,也可以管道符后面的
( )表示一个整体 (dog)+ 包含dog整体,出现一次或多次 (123|asd)? 包含123整体或asd整体出现0次或1次
egrep中    .  { }  不再需要 \ 转义符

对应grep的前一个字符出现n次则列出
[root@localhost ~]# cat /root/kuozhan.txt 
love is lover
like is liker
love is liker
like is lover

[root@localhost ~]# egrep "(l..e).*(\1)" /root/kuozhan.txt 			#(\1)表示匹配前面已经找到的单元
love is lover
like is liker
#过滤ip
[root@localhost ~]# cat /root/test.txt 
192.168.32.200
192.168.a.200
a192.168.32.200
192.168.32.256
192.168.32.200b
8.8.8.8
300.300.12.13
8.8.8.
10.10.10.10
11.11.11.11
10.10.11.10
1.2.4.3
1.3.2.
1.0.0.0
127.a.0.1
127.0.0.1
[root@localhost ~]# egrep "(^[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])$" /root/test.txt
192.168.32.200
8.8.8.8
10.10.10.10
11.11.11.11
10.10.11.10
1.2.4.3
1.0.0.0
127.0.0.1

二 字符截命令、替换命令

1 cut (默认以TAB为分隔符)

选项作用
-f n截取第n列 -f n,m 截取n和m列
-c -n截取每一行的前n个字符(包括tab、空格)
-d " "指定分隔符截取, -d ":" -f 1 指定:为分隔符,截取第一列
#批量创建用户、批量删除用户
[root@localhost ~]# for i in {1..10}						#批量创建用户
> do
> useradd yq$i
> done
[root@localhost ~]# grep "/bin/bash$" /etc/passwd |cut -d ":" -f 1 |grep -v root		#grep结合cut过滤新建的用户
yq1
yq2
yq3
yq4
yq5
yq6
yq7
yq8
yq9
yq10
[root@localhost ~]# del=$(grep "/bin/bash$" /etc/passwd |cut -d ":" -f 1 |grep -v root)			#定义变量
[root@localhost ~]# for j in $del															#批量删除用户
> do
> userdel $j
> done
[root@localhost ~]# tail -n 10 /etc/passwd													#检查删除成功
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
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
[root@localhost ~]# grep "/bin/bash$" /etc/passwd |cut -d ":" -f 1 |grep -v root			#检查删除成功

2 awk

awk认为文件是结构化(即由单词、空白字符组成)(空白字符包括空格、TAB、连续空格、连续TAB)

1) 每个非空白部分叫做“域”
$0		全部域
$n		表示第n个域,(n大于等于1)
2) printf格式化输出(重新定义格式,输出内容)
格式:
		printf       '输出类型输出格式'    输出内容

输出类型:
		%ns					#字符串 			“%-ns  表示左对齐     %ns表示右对齐”  
		%ni					#整数				“%-ni	表示左对齐	%ni表示右对齐”
		%m.nf				#浮点数(小数)	(mn表示位个数)

输出格式:(要加双引号)
		\n					#换行
		\t					#tab键
[root@localhost ~]# cat ./cj.txt
ID	Name	gender	Mark
1	zhaosan	M	87
2	lisi	M	90
3	wangwu	M	89

[root@localhost ~]# printf "%s\t%s\t%s\t%s\n" $(cat ./cj.txt)
ID	Name	gender	Mark
1	zhaosan	M	87
2	lisi	M	90
3	wangwu	M	89
[root@localhost ~]# printf "%s\t%s\t%s\t%s\n" $(cat ./cj.txt|grep -v Name)
1	zhaosan	M	87
2	lisi	M	90
3	wangwu	M	89

3) awk基本使用
格式:
		awk		'条件1{动作1}   条件2{动作2}......'    文件名

条件:
		x  >  0		#大于0
		x == y		#x=y
		A!~B		#反选B

	awk			-F		":"			#指定:分隔符列截取
[root@localhost ~]# df -h
文件系统        容量  已用  可用 已用% 挂载点
/dev/sda3        20G  1.1G   19G    6% /
devtmpfs        476M     0  476M    0% /dev
tmpfs           487M     0  487M    0% /dev/shm
tmpfs           487M  7.7M  479M    2% /run
tmpfs           487M     0  487M    0% /sys/fs/cgroup
/dev/sda1       509M  120M  389M   24% /boot
tmpfs            98M     0   98M    0% /run/user/0
/dev/sr0        4.3G  4.3G     0  100% /mnt
[root@localhost ~]# df -h |awk '{printf $2 "\t" $6 "\n"}'				#格式化输出低2列,tab,第六列
容量	挂载点
20G	/
476M	/dev
487M	/dev/shm
487M	/run
487M	/sys/fs/cgroup
509M	/boot
98M	/run/user/0
4.3G	/mnt
[root@localhost ~]# df -h |awk '{printf "%-30s %-30s\n",$1,$5}'			#格式化输出,左右对齐,第1列,第6列,列之间用,隔开
文件系统                           已用%                           
/dev/sda3                      6%                            
devtmpfs                       0%                            
tmpfs                          0%                            
tmpfs                          2%                            
tmpfs                          0%                            
/dev/sda1                      24%                           
tmpfs                          0%                            
/dev/sr0                       100%                          
[root@localhost ~]# awk -F ":" '{printf "%19s\n",$1}' /etc/passwd		#指定:分隔符截取第一列,右对齐
               root
                bin
             daemon
                adm
                 lp
               sync
           shutdown
               halt
               mail
           operator
              games
                ftp
             nobody
    systemd-network
               dbus
            polkitd
               sshd
            postfix
             chrony
[root@localhost ~]# awk -F ":" '{printf "%-15s %15s\n",$1,$NF}' /etc/passwd			#     $NF表示最后一行
root                  /bin/bash
bin               /sbin/nologin
daemon            /sbin/nologin
adm               /sbin/nologin
lp                /sbin/nologin
sync                  /bin/sync
shutdown         /sbin/shutdown
halt                 /sbin/halt
mail              /sbin/nologin
operator          /sbin/nologin
games             /sbin/nologin
ftp               /sbin/nologin
nobody            /sbin/nologin
systemd-network   /sbin/nologin
dbus              /sbin/nologin
polkitd           /sbin/nologin
sshd              /sbin/nologin
postfix           /sbin/nologin
chrony            /sbin/nologin
[root@localhost ~]# awk -F ":" '{printf "USERNAME: %-15s %15s\n",$1,$NF}' /etc/passwd		#  每行输出都用USERNAME开头
USERNAME: root                  /bin/bash
USERNAME: bin               /sbin/nologin
USERNAME: daemon            /sbin/nologin
USERNAME: adm               /sbin/nologin
USERNAME: lp                /sbin/nologin
USERNAME: sync                  /bin/sync
USERNAME: shutdown         /sbin/shutdown
USERNAME: halt                 /sbin/halt
USERNAME: mail              /sbin/nologin
USERNAME: operator          /sbin/nologin
USERNAME: games             /sbin/nologin
USERNAME: ftp               /sbin/nologin
USERNAME: nobody            /sbin/nologin
USERNAME: systemd-network   /sbin/nologin
USERNAME: dbus              /sbin/nologin
USERNAME: polkitd           /sbin/nologin
USERNAME: sshd              /sbin/nologin
USERNAME: postfix           /sbin/nologin
USERNAME: chrony            /sbin/nologin
4) awk 条件
awk		'{动作}'		文件名								#执行花括号动作
awk			'条件{动作}'		文件名					  #符合条件则执行动作

保留字:

BEGIN					开始时执行
END						结束时执行

关系运算符:

	>		<			<=			>=
	==					#等于
	!=					#不等于
	~					#包含
	!~					#不包含

正则表达式:

/正则表达式/						//中间可以写字符,也可写正则表达式
[root@localhost ~]# cat cj.txt 
ID	Name	gender	Mark
1	zhaosan	M	87.234
2	lisi	M	90.34524
3	wangwu	M	89.21356
[root@localhost ~]# awk '{printf "开始-----\n"} {printf $2 "\t" $4 "\n"}' /root/cj.txt 
开始-----
Name	Mark
开始-----
zhaosan	87.234
开始-----
lisi	90.34524
开始-----
wangwu	89.21356
开始-----
	
[root@localhost ~]# awk 'BEGIN{printf "开始-----\n"} {printf $2 "\t" $4 "\n"}' /root/cj.txt 		#BEGIN	开始时执行
开始-----
Name	Mark
zhaosan	87.234
lisi	90.34524
wangwu	89.21356

#BEGIN		开始时执行
#END		结束时执行
[root@localhost ~]# awk 'BEGIN{printf "开始-----\n"} {printf $2 "\t" $4 "\n"} END{printf "结束------\n"}' /root/cj.txt 
开始-----
Name	Mark
zhaosan	87.234
lisi	90.34524
wangwu	89.21356
	
结束------


[root@localhost ~]# grep -v "ID" /root/cj.txt | awk '$4>=89{printf $2 "\t" $4 "\n"}'
lisi	90.34524
wangwu	89.21356
[root@localhost ~]# grep -v "ID" /root/cj.txt | awk 'BEGIN{printf "优秀的人有:\n"}$4>=89{printf $2 "\t" $4 "\n"}'
优秀的人有:
lisi	90.34524
wangwu	89.21356
[root@localhost ~]# awk '$2~/lisi/ {printf $4 "\n"}' /root/cj.txt 				#	~	包含
90.34524
[root@localhost ~]# awk 'BEGIN{printf "lisi成绩是:\n"}$2~/lisi/ {printf $4 "\n"}' /root/cj.txt 
lisi成绩是:
90.34524
[root@localhost ~]# awk 'BEGIN{printf "lisi信息有:\n"}$2~/lisi/ {print}' /root/cj.txt 
lisi信息有:
2	lisi	M	90.34524
[root@localhost ~]# awk 'BEGIN{printf "lisi信息有:\n"}$2~/lisi/ {printf $0}' /root/cj.txt 
lisi信息有:
2	lisi	M	90.34524[root@localhost ~]# 
[root@localhost ~]# awk 'BEGIN{printf "lisi信息有:\n"}$2~/lisi/ {printf $0 "\n"}' /root/cj.txt 
lisi信息有:
2	lisi	M	90.34524

[root@localhost ~]# df -h |awk '/sda[0-9]/ {print $1 "\t" $5}'			#查找包含//中的字符进行列提取
/dev/sda3	6%
/dev/sda1	24%
[root@localhost ~]# df -h |awk '/sda[0-9]/ {printf $1 "\t" $5 "\n"}'
/dev/sda3	6%
/dev/sda1	24%
[root@localhost ~]# df -h | awk '/sda[0-9]/ {printf $1 "\t" $5 "\n"}' |cut -d "%" -f 1 
/dev/sda3	6
/dev/sda1	24
[root@localhost ~]# df -h | awk '/sda[0-9]/ {printf $1 "\t" $5 "\n"}' |cut -d "%" -f 1 |awk 'BEGIN{printf "使用存储已经超过20%:"} $2>20{printf $1 "\n"}'
使用存储已经超过20%:/dev/sda1

5) awk内置变量:
awk内置变量作用
$0当前读入行的整行
$n当前读入行的第n个字段
NF当前拥有的字段(列)总数
NR当前数据的第n行
FS用户自定义分隔符,在动作中执行 BEGIN{FS=":"} 执行命令截取前生效

调用文件的规则,awk截取:

$ awk  -f
[root@localhost ~]# cat /etc/passwd |grep "/bin/bash" |awk 'BEGIN{FS=":"}{printf$1 "\t" $3 "\n"}'
root	0
yq1	1000
yq2	1001
yq3	1002
[root@localhost ~]# cat /etc/passwd |grep "/bin/bash" |awk 'BEGIN{FS=":"}{printf $1 "\t" $3 "\n"}'
root	0
yq1	1000
yq2	1001
yq3	1002
[root@localhost ~]# cat /etc/passwd |grep "/bin/bash" |cut -d ":" -f 1,3
root:0
yq1:1000
yq2:1001
yq3:1002
[root@localhost ~]# cat /etc/passwd |grep "/bin/bash" |awk -F ":" '{printf $1 "\t" $3 "\n"}'
root	0
yq1	1000
yq2	1001
yq3	1002

#  NR  当前数据的第n行
[root@localhost ~]# awk 'NR==2{cj1=$4};NR==3{cj2=$4};NR==4{cj3=$4;totle=cj1+cj2+cj3;printf "总成绩是:"totle "\n"}' /root/cj.txt
总成绩是:266.793
[root@localhost ~]# awk 'NR==2{cj1=$4};Nr==3{cj2=$4};NR==4{cj3=$4;average=(cj1+cj2+cj3)/3;printf "平均成绩是:"average"\n"}' /root/cj.txt 
平均成绩是:58.8159
#awk实现判断
[root@localhost ~]# awk '{if (NR>=2){if ($4>=90) printf $2 "\t很优秀\n"}}' /root/cj.txt 
lisi	很优秀

#  FS 用户自定义分隔符,在动作中执行
[root@localhost ~]# cat /root/pass.awk 
BEGIN{FS=":"}
{printf "%-20s%20s\n",$1,$3}
[root@localhost ~]# awk -f /root/pass.awk  /etc/passwd				#调用文件的规则,awk截取:		awk		-f
root                                   0
bin                                    1
daemon                                 2
adm                                    3
lp                                     4
sync                                   5
shutdown                               6
halt                                   7
mail                                   8
operator                              11
games                                 12
ftp                                   14
nobody                                99
systemd-network                      192
dbus                                  81
polkitd                              999
sshd                                  74
postfix                               89
chrony                               998
yq1                                 1000
yq2                                 1001
yq3                                 1002

3 sed命令

默认不修改硬盘源文件,在内存中执行,成为模式空间 (加 -i 选项后则永久修改)

格式:
	 sed		[选项]		'[动作]'		文件名
选项:
		-n					# 仅将修改的输出到屏幕
		-e					# 多动作执行,或者将多动作用 ;隔开
		-f		脚本文件名	 # 从脚本中读入sed操作,类似awk		-f
		-r					# 在sed中支持扩展正则表达式
		-i					# 永久修改源文件

动作:

动作作用
a添加 添加多行时,在末尾加上\继续添加下一行
c替换(整行)
i插入,在当前插入一行或多行
d删除
p输出
s替换(字符串) s/old/new s/old/new/g 全替换 s/old/new/2 仅替换第二个old为new
[root@localhost ~]# cat /root/cj.txt 
ID	Name	gender	Mark
1	zhaosan	M	87.234
2	lisi	M	90.34524
3	wangwu	M	89.21356

[root@localhost ~]# sed '1p' ./cj.txt 				#输出(仅显示)
ID	Name	gender	Mark
ID	Name	gender	Mark
1	zhaosan	M	87.234
2	lisi	M	90.34524
3	wangwu	M	89.21356

[root@localhost ~]# sed '4p' ./cj.txt 				
ID	Name	gender	Mark
1	zhaosan	M	87.234
2	lisi	M	90.34524
3	wangwu	M	89.21356
3	wangwu	M	89.21356

[root@localhost ~]# sed '1,3d' ./cj.txt 				#删除1到3行
3	wangwu	M	89.21356

[root@localhost ~]# sed '2a AAAA' ./cj.txt 				#添加1行
ID	Name	gender	Mark
1	zhaosan	M	87.234
AAAA
2	lisi	M	90.34524
3	wangwu	M	89.21356

[root@localhost ~]# sed '2a AAAAA\						#添加多行
> BBBBB\
> CCCCC' ./cj.txt
ID	Name	gender	Mark
1	zhaosan	M	87.234
AAAAA
BBBBB
CCCCC
2	lisi	M	90.34524
3	wangwu	M	89.21356

#整行替换,以本地源文件为例
[root@localhost ~]# grep -n "baseurl" /etc/yum.repos.d/CentOS-Media.repo 
16:baseurl=file:///media/CentOS/
[root@localhost ~]# grep -n "baseurl" /etc/yum.repos.d/CentOS-Media.repo |awk -F ":" '{print $1}'
16
[root@localhost ~]# aa=$(grep -n "baseurl" /etc/yum.repos.d/CentOS-Media.repo |awk -F ":" '{print $1}')
[root@localhost ~]# sed "${aa}c baseurl=file:///mnt" /etc/yum.repos.d/CentOS-Media.repo 					#整行替换
[c7-media]
name=CentOS-$releasever - Media
baseurl=file:///mnt
        file:///media/cdrom/
        file:///media/cdrecorder/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

[root@localhost ~]# grep -n "file:///media/cdrom/" /etc/yum.repos.d/CentOS-Media.repo |cut -d ":" -f 1
17
[root@localhost ~]# bb=$(grep -n "file:///media/cdrom/" /etc/yum.repos.d/CentOS-Media.repo |cut -d ":" -f 1)
[root@localhost ~]# cc=$(grep -n "file:///media/cdrecorder/" /etc/yum.repos.d/CentOS-Media.repo |cut -d ":" -f 1)
[root@localhost ~]# sed "${bb}d;${cc}d;${aa}c baseurl=file:///mnt " /etc/yum.repos.d/CentOS-Media.repo 			#整行替换和整行删除
[c7-media]
name=CentOS-$releasever - Media
baseurl=file:///mnt 
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#字符串替换
[root@localhost ~]# grep -n "enabled" /etc/yum.repos.d/CentOS-Media.repo 
20:enabled=0
[root@localhost ~]# grep -n "enabled" /etc/yum.repos.d/CentOS-Media.repo |awk -F ":" '{print $1}'
20
[root@localhost ~]# dd=$(grep -n "enabled" /etc/yum.repos.d/CentOS-Media.repo |awk -F ":" '{print $1}')
[root@localhost ~]# sed "${dd}s/0/1/1" /etc/yum.repos.d/CentOS-Media.repo					#仅替换enabled行的第一个0为1
[c7-media]
name=CentOS-$releasever - Media
baseurl=file:///media/CentOS/
        file:///media/cdrom/
        file:///media/cdrecorder/
gpgcheck=1
enabled=1	#0表示不启用;1表示启用
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#将整行替换、整行删除、字符串替换结合到一起,配置本地源文件
[root@localhost ~]# sed "${dd}s/0/1/1;${bb}d;${cc}d;${aa}c baseurl=file:///mnt" /etc/yum.repos.d/CentOS-Media.repo
[c7-media]
name=CentOS-$releasever - Media
baseurl=file:///mnt
gpgcheck=1
enabled=1	#0表示不启用;1表示启用
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

替换扩展:

[root@localhost ~]# sed '/SELINUX/ s/enforcing/disabled/' /etc/selinux/config 			#字符替换

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected. 
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted 


[root@localhost ~]# sed '/SELINUX/ !s/enforcing/disabled/' /etc/selinux/config 			#反选字符替换

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     disabled - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of disabled.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected. 
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted 

[root@localhost ~]# sed '/man/,/swap/ s/xfs/ext4/g' /root/fstab 					#字符范围替换

#
# /etc/fstab
# Created by anaconda on Tue Aug 23 00:55:11 2022
#
# 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
#
ext4   ext4    ext4   ext4 ext4ext4 ext4ext4ext4
UUID=f72c2294-cf5d-4138-b100-a8c5b24d028e /                       ext4     defaults        0 0
UUID=4fe405ff-6ef5-48ff-a82e-c8598b2af188 /boot                   ext4     defaults        0 0
UUID=5837e45a-8e89-4085-a347-0ec7b68fa53e swap                    swap    defaults        0 0


[root@localhost ~]# ee=$(grep -n "xfsxfs" /root/fstab |awk -F ":" '{print $1}')
[root@localhost ~]# echo $ee
9
[root@localhost ~]# sed "${ee}s/^/#/" /root/fstab 										#将含有xfsxfs的一行注释
#
# /etc/fstab
# Created by anaconda on Tue Aug 23 00:55:11 2022
#
# 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
#
#xfs   xfs    xfs   xfs xfsxfs xfsxfsxfs
UUID=f72c2294-cf5d-4138-b100-a8c5b24d028e /                       xfs     defaults        0 0
UUID=4fe405ff-6ef5-48ff-a82e-c8598b2af188 /boot                   xfs     defaults        0 0
UUID=5837e45a-8e89-4085-a347-0ec7b68fa53e swap                    swap    defaults        0 0

三 字符处理命令

1 sort排序

sort			[选项]		文件名
					-f				忽略大小写
					-r				反向排序
					-n				以数值型进行排序,默认以字符串排序

2 uniq

统计连续重复的行
		uniq			[选项]		文件名
							-i				忽略大小写
							-c				取消重复行,且统计重复出现次数
[root@localhost ~]# cat ./test.txt 
AAAAAAA
BBBBBBB
CCCCCCC
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
CCCCCCC
CCCCCCC
CCCCCCC
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
[root@localhost ~]# uniq -c ./test.txt 				#统计重复行
      1 AAAAAAA
      1 BBBBBBB
      1 CCCCCCC
      6 AAAAAAA
      3 CCCCCCC
      6 AAAAAAA
[root@localhost ~]# sort ./test.txt 				#排序
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
AAAAAAA
BBBBBBB
CCCCCCC
CCCCCCC
CCCCCCC
CCCCCCC
[root@localhost ~]# sort ./test.txt | uniq -c 			#排序后统计重复行
     13 AAAAAAA
      1 BBBBBBB
      4 CCCCCCC

写两个脚本

sed实现本地源、sed和read实现交互式配置ip

#配置本地源
[root@localhost ~]# cat ./yuan.sh 
#!/bin/bash
#创建挂载点
read -p "请输入挂载点(以/开头):" point
if [ "$point" == "" ];then
	new=$(echo "您未选择挂载点,正在退出---")
	x=${z-$new}
	echo "$x"
else
	mkdir $point
	while [ "$?" == "1" ]
	do 
		read -p "请重新输入挂载点(以/开头):" point
		if [ "$point" == "" ];then
        		new=$(echo "您未选择挂载点,正在退出---")
        		x=${z-$new}
        		echo "$x"
		else		
			mkdir $point
		fi
	done 
	echo "创建挂载点成功-------"
fi
#挂载光盘
a1=$(df -h |grep "/dev/sr0" |awk '{print $1}')
if [ "$a1" == "/dev/sr0" ];then
	for i in {1..20}
	do
		umount $a1
	done
else
	echo ""
fi
mount -t iso9660 /dev/sr0 $point
#配置本地源
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak
if [ "$?" == "0" ] ;then
	echo "网络源注释成功,进行下一步"
else
	echo " "
fi
aa=$(grep -n "baseurl" /etc/yum.repos.d/CentOS-Media.repo |awk -F ":" '{print $1}')
bb=$(grep -n "file:///media/cdrom/" /etc/yum.repos.d/CentOS-Media.repo | cut -d ":" -f 1)
cc=$(grep -n "file:///media/cdrecorder/" /etc/yum.repos.d/CentOS-Media.repo |cut -d ":" -f 1)
dd=$(grep -n "enabled" /etc/yum.repos.d/CentOS-Media.repo |awk -F ":" '{print $1}')
sed -i "${dd}s/0/1/1;${cc}s/^/#/;${bb}s/^/#/;${aa}c baseurl=file://$point" /etc/yum.repos.d/CentOS-Media.repo
echo "本地源文件配置成功---------------"

#配置yum
yum clean all && yum makecache


#交互式配置ip
[root@localhost ~]# cat ./ip.sh 
#!/bin/bash
read -p "请选择ip获取方式[d(dhcp)/s(static)]:" aa1
bb1=$(grep -n "BOOTPROTO" /etc/sysconfig/network-scripts/ifcfg-ens33 | awk -F ":" '{print $1}')
bb2=$(grep -n "ONBOOT" /etc/sysconfig/network-scripts/ifcfg-ens33 |awk -F ":" '{print $1}')
if [ -n "$aa1" ];then
	if [ "$aa1" == "s" ];then
		sed -i "${bb1}c BOOTPROTO=static" /etc/sysconfig/network-scripts/ifcfg-ens33
		read -p "请输入ip:" cc1
		ff1=$(grep -n "IPADDR" /etc/sysconfig/network-scripts/ifcfg-ens33 |cut -d ":" -f 1)
		if [ -z "$ff1" ];then
			echo "IPADDR=$cc1" >> /etc/sysconfig/network-scripts/ifcfg-ens33
		else
			sed -i "${ff1}c IPADDR=$cc1" /etc/sysconfig/network-scripts/ifcfg-ens33
		fi
		read -p "是否使用默认netmask为255.255.255.0(y/n):" cc2
		ff2=$(grep -n "NETMASK" /etc/sysconfig/network-scripts/ifcfg-ens33 |cut -d ":" -f 1) 
		if [ -z "$ff2" ];then
			if	[ "$cc2" == "y" ];then
				echo "NETMASK=255.255.255.0" >> /etc/sysconfig/network-scripts/ifcfg-ens33
			else
				read -p "请输入netmask:" ee1
				echo "NETMASK=$ee1" >> /etc/sysconfig/network-scripts/ifcfg-ens33
			fi
		else
			if	[ "$cc2" == "y" ];then
				sed -i "${ff2}c NETMASK=255.255.255.0" /etc/sysconfig/network-scripts/ifcfg-ens33
			else
				read -p "请输入netmask:" ee1
				sed -i "${f22}c NETMASK=$ee1" /etc/sysconfig/network-scripts/ifcfg-ens33
			fi
		fi
		read -p "是否使用默认网关为192.168.18.2(y/n):" cc3
		ff3=$(grep -n "GATEWAY" /etc/sysconfig/network-scripts/ifcfg-ens33 |cut -d ":" -f 1)  
		if [ -z "$ff3" ];then
			if [ "$cc3" == "y" ];then
				echo "GATEWAY=192.168.18.2" >> /etc/sysconfig/network-scripts/ifcfg-ens33
			else
				read -p "请输入网关(GATEWAY):" cc3
				echo "GATEWAY=$cc3" >> /etc/sysconfig/network-scripts/ifcfg-ens33
			fi
		else
			if [ "$cc3" == "y" ];then
				sed -i "${ff3}c GATEWAY=192.168.18.2" /etc/sysconfig/network-scripts/ifcfg-ens33
			else
				read -p "请输入网关(GATEWAY):" cc3
				sed -i "${ff3}c GATEWAY=$cc3" /etc/sysconfig/network-scripts/ifcfg-ens33
			fi
		fi
		read -p "是否使用默认DNS114.114.114.114(y/n):" cc4
		ff4=$(grep -n "DNS1" /etc/sysconfig/network-scripts/ifcfg-ens33 |cut -d ":" -f 1)
		if [ -z "$ff4" ];then
			if [ "$cc4" == "y" ];then
				echo "DNS1=114.114.114.114" >> /etc/sysconfig/network-scripts/ifcfg-ens33
			else
				read -p "请输入DNS:" cc4
				echo "DNS1=$cc4" >> /etc/sysconfig/network-scripts/ifcfg-ens33
			fi
		else
			if [ "$cc4" == "y" ];then
				sed -i "${ff4}c DNS1=114.114.114.114" /etc/sysconfig/network-scripts/ifcfg-ens33
			else
				read -p "请输入DNS:" cc4
				sed -i "${ff4}c DNS1=$cc4" /etc/sysconfig/network-scripts/ifcfg-ens33
			fi
		fi
	else
		sed  -i "${bb1}c BOOTPROTO=dhcp" /etc/sysconfig/network-scripts/ifcfg-ens33
	fi
else
	echo "您未选择------"
fi

read -p "请选择是否开机自动配ip(y/n):" bb3
if [ -n "$bb3" ];then
	if [ "$bb3" == "y" ];then
		sed -i "${bb2}c ONBOOT=yes" /etc/sysconfig/network-scripts/ifcfg-ens33
	else
		read -p "请注意----当前终端将会断开,且服务器将没有ip-------是否继续(y/n):" ee2
		if [ "$ee2" == "y" ];then
			sed -i "${bb2}c ONBOOT=no" /etc/sysconfig/network-scripts/ifcfg-ens33
		else
			exit
		fi
	fi
else
echo "您未选择-----正在进行下一个选择--------"
fi

echo "请注意------重启网卡后,当前终端可能会断开-------"
read -p "是否重启网卡(y/n):" bb4
if [ -n "$bb3" ];then
	if [ "$bb4" == "y" ];then
		if [ "$aa1" == "s" ];then
			echo "您的IP是:$cc1"
		else
			dd1=$(ip addr | grep "inet 192" |awk -F " " '{print $2}' |cut -d "/" -f 1)
			echo "您的IP是:$dd1"
		fi
		echo "正在重启网卡-----"  
		echo "如果远程连接断开,请根据上面IP重新远程连接-----------------"
		systemctl restart network 
	else
		echo "若不重启网卡,需要您手动重启网卡-------"
	fi
else
	echo "您未选择-------正在退出--------"
fi