SHELL 基础(四)

一、SED流式编辑器

1、sed语法

sed是流式编辑器,处理文件内容时逐行处理
sed [选项] '[定位符]指令'  文件

[root@SHELL ~]# sed '' /etc/resolv.conf         #打印文件所有的行,由sed默认的输出功能打印
[root@SHELL ~]# sed -n 'p' /etc/resolv.conf     #打印文件所有行,—n屏蔽了默认数据,由p指令实现打印

2、sed的定位符

行号定位

[root@SHELL ~]# sed -n '3p' /etc/passwd         #打印第3行
[root@SHELL ~]# sed -n '1,3p' /etc/passwd       #打印1到3行
[root@SHELL ~]# sed -n '1~2p' /etc/passwd       #打印从第1行开始,步长为2的行,奇数行
[root@SHELL ~]# sed -n '2~2p' /etc/passwd       #打印从第2行开始,步长为2的行,偶数行
[root@SHELL ~]# sed -n '2,+3p' /etc/passwd      #第2行及其后边的3行
[root@SHELL ~]# sed -n '1p;4p;8p' /etc/passwd   #打印第1行、第4行、第8行
​

正则定位(sed默认使用标准正则)

[root@SHELL ~]# cat /etc/passwd | grep "^root"
[root@SHELL ~]# sed -n '/^root/p' /etc/passwd               #过滤root开头的行
[root@SHELL ~]# cat /etc/passwd | grep "[0-9]\{3\}" 
[root@SHELL ~]# cat /etc/passwd | sed -n '/[0-9]\{3\}/p'    #过滤包含3个数字的行

3、sed指令

##处理级别:行

#p指令打印
[root@SHELL ~]# sed -n '/IPADDR/p' /etc/sysconfig/network-scripts/ifcfg-eth0    #打印符合条件指定行
[root@SHELL ~]# free -m | sed -n '/Mem/p'           #打印符合条件指定行
[root@SHELL ~]# df -h | sed -n '/\/$/p'             #打印符合条件指定行
[root@SHELL ~]# sed -n '/localhost/!p' /etc/hosts   #打印不包括localhost的行
[root@SHELL ~]# sed -n '2!p' /etc/hosts             #打印不是第2行的行

#d指令删除
[root@SHELL ~]# cp /etc/fstab /tmp/
[root@SHELL ~]# ls /tmp/fstab 
[root@SHELL ~]# sed 'd' /tmp/fstab                  #把该默认打印的行删除,删除所有
[root@SHELL ~]# sed '1d' /tmp/fstab                 #删除指定行
[root@SHELL ~]# sed '/dev/d' /tmp/fstab             #删除带dev的行
[root@SHELL ~]# sed '/dev/!d' /tmp/fstab            #删除不带dev的行
[root@SHELL ~]# sed '/^#/d' /tmp/fstab              #删除#开头行(注释行)
[root@SHELL ~]# sed '/^$/d' /tmp/fstab              #删除空行
​
#c指令替换整行
[root@SHELL ~]# sed 'c123456' /tmp/fstab
[root@SHELL ~]# sed '/IPADDR/cIPADDR=1.1.1.1' /etc/sysconfig/network-scripts/ifcfg-eth0
[root@SHELL ~]# sed '4cxxxxxx' /etc/shells
​
#s指令替换关键词
[root@SHELL day04]# cat test.txt 
2046 2048 2046 2046
1001 2046 2999 1888
2046 2046 2046 2046
[root@SHELL day04]# sed 's/2046/XXXX/' test.txt         #替换每行第1个
XXXX 2048 2046 2046
1001 XXXX 2999 1888
XXXX 2046 2046 2046 
[root@SHELL day04]# sed 's/2046/XXXX/g' test.txt        #替换每行所有
XXXX 2048 XXXX XXXX
1001 XXXX 2999 1888
XXXX XXXX XXXX XXXX
[root@SHELL day04]# sed 's/2046/XXXX/2' test.txt        #替换每行指定第几个匹配结果替换
2046 2048 XXXX 2046
1001 2046 2999 1888
2046 XXXX 2046 2046
[root@SHELL day04]# sed 's/2046/(&)/g' test.txt         #&代替旧的字符
(2046) 2048 (2046) (2046)
1001 (2046) 2999 1888
(2046) (2046) (2046) (2046) 
[root@SHELL day04]# sed '2s/2046/XXXX/g' test.txt       #指定替换第2行
2046 2048 2046 2046
1001 XXXX 2999 1888
2046 2046 2046 2046
[root@SHELL day04]# sed '2s/2046//g' test.txt           #替换为空
2046 2048 2046 2046
1001  2999 1888
2046 2046 2046 2046
[root@SHELL day04]# sed -n '2s/2046//gp' test.txt       #指定行替换为空
1001  2999 1888
[root@SHELL day04]# sed 's.2046.XXXX.' test.txt         #s///中/可以写为任意字符
​
[root@SHELL day04]# sed 's2\20462\20\2\22g' test.txt 
                        s/2046/2022/   
                        sa2046a2022a
                        s2  \2046 2 \20\2\2  2
​
[root@SHELL day04]# echo "hello world" | sed -rn 's/^(.)(.*)(.)$/\3\2\1/p'
dello worlh
​
#=等于号用于打印行号
[root@SHELL day04]# sed -n '/root/=' /etc/passwd        #匹配带root的行,打印行号
1
10
[root@SHELL day04]# sed -n '/bash$/=' /etc/passwd       #匹配bash结尾的行,打印行号
[root@SHELL day04]# sed -n '$=' /etc/passwd             #打印最后一行行号,即行数
​
#i行前写入
[root@SHELL day04]# sed 'iabc_xyz' test.txt         #所有行前加入指定内容
abc_xyz
2046 2048 2046 2046
abc_xyz
1001 2046 2999 1888
abc_xyz
2046 2046 2046 2046
[root@SHELL day04]# sed '2iabc_xyz' test.txt        #指定行号前加入指定内容
2046 2048 2046 2046
abc_xyz
1001 2046 2999 1888
2046 2046 2046 2046
[root@SHELL day04]# sed '/2046/i abc_xyz' test.txt #正则匹配行前写入
abc_xyz
2046 2048 2046 2046
abc_xyz
1001 2046 2999 1888
abc_xyz
2046 2046 2046 2046
​
#a指令行后写入
[root@SHELL day04]# sed 'aabc_xyz' test.txt         #所有行后写入
2046 2048 2046 2046
abc_xyz
1001 2046 2999 1888
abc_xyz
2046 2046 2046 2046
abc_xyz
[root@SHELL day04]# sed '2aabc_xyz' test.txt        #指定行后写入
2046 2048 2046 2046
1001 2046 2999 1888
abc_xyz
2046 2046 2046 2046
[root@SHELL day04]# sed '/2046/aabc_xyz' test.txt   #匹配行后写入
2046 2048 2046 2046
abc_xyz
1001 2046 2999 1888
abc_xyz
2046 2046 2046 2046
abc_xyz
[root@SHELL day04]# 
​
#r从文件读入
[root@SHELL day04]# sed 'r /etc/hosts' test.txt             #读入文件内容,所有行后
[root@SHELL day04]# sed '2r /etc/hosts' test.txt            #读入文件内容,指定行后
[root@SHELL day04]# sed '/1888/r /etc/hosts' test.txt       #读入文件内容,匹配行后
​
#w另存为
[root@SHELL day04]# sed 'w copy_test.txt' test.txt          #所有行另存为
[root@SHELL day04]# cat copy_test.txt 
[root@SHELL day04]# sed '2w test2.txt' test.txt             #指定行另存为
[root@SHELL day04]# cat test2.txt 
[root@SHELL day04]# sed '/1888/w 1888.txt' test.txt         #匹配行另存为
[root@SHELL day04]# cat 1888.txt 

​
 

爬取图片案例

[root@SHELL day04]# cat spider.sh 
#!/bin/bash
curl -s "https://www.tmooc.cn/" > index.html
​
echo "开始处理文件内容"
sed -ri '/<img/!d' index.html
sed -ri 's/.*src="//' index.html
sed -ri '/<img id/d' index.html 
sed -ri 's/".*//' index.html
sed -ri '/^$/d' index.html 
​
if [ -e "./pic" ];then
    echo "pic目录已存在"
else
    mkdir ./pic
    echo "创建pic目录"
fi
​
echo "下载图片"
for i in $(cat index.html)
do
    wget -P ./pic -q $i
done
​
rm -rf index.html
[root@SHELL day04]# 

二、awk工具

1、awk基础语法

用于获取整行数据中的部分数据(获取列)
​语法:命令执行结果 | awk [选项] '[条件]{指令}'
 

[root@SHELL ~]# df -hT | grep "/$" 
/dev/sda1      xfs        20G  1.9G   19G  10% /
[root@SHELL ~]# df -hT | grep "/$" | tr -s " " | cut -d" " -f5
19G
[root@SHELL ~]# df -hT | grep "/$" | awk '{print $5}'
​
#语法:awk [选项] '[条件]{指令}' 文件
[root@SHELL ~]# awk -F: '{print $1,$7}' /etc/passwd
root /bin/bash
bin /sbin/nologin

2、awk内置变量

[root@SHELL ~]# awk -F: '{print NR,NF}' /etc/passwd
​
[root@SHELL ~]# awk -F: '{print $NF}' /etc/hosts
​
[root@SHELL ~]# awk -F:  '{print "用户名是:"$1",""解释器是:"$7}'  /etc/passwd

3、awk流程控制语法(时机)

语法 awk 'BEGIN{}   {}   END{}' 文件
      awk 'BEGIN{处理文件前做的事}     {处理文件时做的事}      {处理文件后做的事}'   文件
      awk '处理前   处理时    处理后'   文件

[root@SHELL ~]# awk 'BEGIN{a=12;print a+23}'
35
[root@SHELL ~]# awk 'BEGIN{print NR}    END{print NR}' /etc/passwd
0
27
[root@SHELL ~]# awk -F: 'BEGIN{print "用户名","\t","解释器"} {print $1,"\t",$7}' /etc/passwd
[root@SHELL ~]# awk -F: 'BEGIN{x=0}  /bash$/{x++}   END{print x}' /etc/passwd

4、awk基础案列

#内存信息
[root@SHELL ~]# free -m | awk '{print $7}'
​
735
​
[root@SHELL ~]# free -m | grep "Mem" | awk '{print $7}'
734
[root@SHELL ~]# free -m | awk /Mem/'{print $7}'
737
[root@SHELL ~]# 
​
#硬盘信息
[root@SHELL ~]# df | awk '/\/$/''{print $4}'
18979752
[root@SHELL ~]# df | awk '/\/$/{print $4}'
18979752
[root@SHELL ~]# 
​
#CPU信息
[root@SHELL ~]# LANG=C lscpu | grep "Model name" | awk -F: '{print $2}'
            12th Gen Intel(R) Core(TM) i7-1260P
[root@SHELL ~]# LANG=C lscpu | awk -F: '/Model name/{print $2}'
            12th Gen Intel(R) Core(TM) i7-1260P
[root@SHELL ~]# LANG=C lscpu | awk -F: '/Model name/{print $2}' | sed -rn 's/(\s*)(.*)/\2/p'
12th Gen Intel(R) Core(TM) i7-1260P
[root@SHELL ~]# 
​
[root@SHELL ~]# uptime 
 01:12:33 up  2:38,  1 user,  load average: 0.00, 0.01, 0.02
[root@SHELL ~]# uptime | awk -F, '{print $5}'
 0.02
[root@SHELL ~]# uptime | awk '{print NF}'
10
[root@SHELL ~]# uptime | awk '{print $NF}'
0.02
[root@SHELL ~]# 

5、awk条件判断

awk [选项] '[条件]{指令}' 文件

#正则  
    匹配:[字段] ~ /正则/
    不匹配:[字段] !~ /正则/
[root@SHELL ~]# awk -F: '/^ro/{print $0}' /etc/passwd 
root:x:0:0:root:/root:/bin/bash
[root@SHELL ~]# awk -F: '$1 ~ /^ro/{print}' /etc/passwd 
root:x:0:0:root:/root:/bin/bash
[root@SHELL ~]# awk -F: '$7 !~ /bash$/{print $0}' /etc/passwd 
bin:x:1:1:bin:/bin:/sbin/nologin
​
#数字、字符串比较
    ==、!=、>、>=、<、<=
[root@SHELL ~]# awk -F: 'NR==2{print $0}' /etc/passwd               #打印行号是2的行
bin:x:1:1:bin:/bin:/sbin/nologin
[root@SHELL ~]# sed -n '2p' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
[root@SHELL ~]# awk -F: '$7 != "/bin/bash"{print $0}' /etc/passwd   #打印解释器不是/bin/bash的
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@SHELL ~]# awk -F: '$3>=1000{print $1}' /etc/passwd            #打印uid大于1000的用户名
tom
jim
​
#逻辑组合
    &&、||
[root@SHELL ~]# awk -F: '$3==0 || $3==7{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
halt:x:7:0:halt:/sbin:/sbin/halt
[root@SHELL ~]# awk -F: '$3>=0 && $3<=3{print $0}' /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
[root@SHELL ~]# 
​
#运算符
+-*/%       ++ -- += -= *= /=
[root@SHELL ~]# awk -F: 'NR%2==1{print $0}' /etc/passwd
​
[root@SHELL ~]# seq 200 | awk 'BEGIN{i=0} {i++} END{print i}'
200
[root@SHELL ~]# seq 200 | awk 'BEGIN{i=0} $0%3==0{i++} END{print i}'
66
[root@SHELL ~]# seq 200 | awk 'BEGIN{i=0} $0%3==0 && $0%13==0{i++} END{print i}'
5
[root@SHELL ~]# 

三、awk流程控制

1、awk if判断

awk '{     if(判断条件){动作}       }' 文件
awk '{   if(判断条件){条件成功动作}     else{条件失败动作}        }' 文件
awk '{if(){}else if(){}..else{}}' 文件

#将条件判断改写为if语句
[root@SHELL ~]# awk -F: 'BEGIN{i=0} $3>=1000{i++} END{print i}' /etc/passwd
7
[root@SHELL ~]# awk -F: 'BEGIN{i=0} {if($3>=1000){i++}} END{print i}' /etc/passwd
7
[root@SHELL ~]#
​
​
[root@SHELL ~]# awk -F: '$1=="root"{print $1,$3}' /etc/passwd       #打印root开头第1/3列
root 0
[root@SHELL ~]# awk -F: '{if($1=="root"){print $1,$3}}' /etc/passwd
root 0
​
[root@SHELL ~]# uptime | awk '$NF>=0.01{print $NF}'
0.01
[root@SHELL ~]# uptime | awk '$NF>=0.01{print "系统十五分钟平均负载:"$NF}'  #NF当前行最后1列
系统十五分钟平均负载:0.01
[root@SHELL ~]# uptime | awk '{if($NF>=0.01){print "系统十五分钟平均负载:"$NF}}'
系统十五分钟平均负载:0.01
[root@SHELL ~]# 
​
[root@SHELL ~]# awk -F: 'BEGIN{i=0;j=0} $3<1000{i++} $3>=1000{j++} END{print "系统 用户数量为:"i,"\n普通用户个数为:",j}' /etc/passwd
系统用户数量为:20 
普通用户个数为: 7
[root@SHELL ~]# awk -F: 'BEGIN{i=0;j=0} {if($3<1000){i++}else{j++}} END{print "系统用户数量为:i,"\n普普通用户个数为:",j}' /etc/passwd
系统用户数量为:20 
普通用户个数为: 7
​
#双分支案例
[root@SHELL ~]# ll /etc/ | awk 'BEGIN{i=0} /^-/{i++} END{print i}'
93
[root@SHELL ~]# ll /etc/ | awk 'BEGIN{i=0} $1~/^-/{i++}  END{print i}'
93
[root@SHELL ~]# ll /etc/ | awk 'BEGIN{i=0;j=0} $1~/^-/{i++} $1!~/^-/{j++} END{print i,j}'
93 89
[root@SHELL ~]# ll /etc/ | awk 'BEGIN{i=0;j=0} $1~/^-/{i++} $1!~/^-/{j++} END{print "文件数量为:"i,"非文件数量为:"j}'
文件数量为:93 非文件数量为:89
[root@SHELL ~]# ll /etc/ | awk 'BEGIN{i=0;j=0} $1~/^-/{i++} $1!~/^-/{j++} END{print "文件数量为:"i,"\n非文件数量为:"j}'
文件数量为:93 
非文件数量为:89
[root@SHELL ~]# ll /etc/ | awk 'BEGIN{i=0;j=0} {if($1~/^-/){i++}else{j++}} END{print "文件数量为:"i,"\n非文件数量为:"j}'
文件数量为:93 
非文件数量为:89
[root@SHELL ~]# 
​
#多分支
[root@SHELL ~]# ll /etc/ | awk 'BEGIN{i=0;j=0;k=0} /^-/{i++} /^d/{j++} /!^[-d]/{k++}END{print i,j,k}'
93 72 0
[root@SHELL ~]# ll /etc/ | awk 'BEGIN{i=0;j=0;k=0} /^-/{i++} /^d/{j++} !/^[-d]/{k++}END{print i,j,k}'
93 72 17
[root@SHELL ~]# ll /etc/ | awk 'BEGIN{i=0;j=0;k=0} $1~/^-/{i++} $1~/^d/{j++} $1!~/^[-d]/{k++} END{print i,j,k}'
93 72 17
[root@SHELL ~]# ll /etc/ | awk 'BEGIN{i=0;j=0;k=0} {if($1~/^-/){i++}else if($1~/^d/){j++}else{k++}} END{print i,j,k}'
93 72 17
[root@SHELL ~]# ll /etc/ | awk 'BEGIN{i=0;j=0;k=0} {if($1~/^-/){i++}else if($1~/^d/){j++}else{k++}} END{print "文件数量为:"i,"\n目录数量为:"j,"\n其他类型文件数量为:"k}'
文件数量为:93 
目录数量为:72 
其他类型文件数量为:17
[root@SHELL ~]# 

2、awk for循环

awk '{for(exp1;exp2;exp3){指令}}' 文件

[root@SHELL ~]# awk 'BEGIN{for(i=1;i<=5;i++){print i}}'
1
2
3
4
5
[root@SHELL ~]# awk 'BEGIN{for(i=5;i>=1;i--){print i}}'
5
4
3
2
1
[root@SHELL ~]# 

四、awk数组

awk 'BEGIN{初始化数组} {数组[下标]++} END{for(下标 in 数组){print 下标,数组[下标]}}' 文件

格式记忆法:[a:1,b:2,c:3],不是真的这样,这个格式仅用于记忆数据结构

[root@SHELL ~]# awk 'BEGIN{name[0]="tom";name[1]="bob";print name[0],name[1]}'
tom bob
[root@SHELL ~]# awk 'BEGIN{name[0]="tom";name[1]="bob";print name[0];print name[1]}'
tom
bob
​
[root@SHELL ~]# awk 'BEGIN{age["tom"]=22;age["bob"]=18;print age["tom"],age["bob"]}'
22 18
​
[root@SHELL ~]# awk 'BEGIN{x[0]=0;x[1]=1;x[2]=2; for(i in x){print i,x[i]}}'
0 0
1 1
2 2
[root@SHELL ~]# awk 'BEGIN{age["tom"]=22;age["bob"]=18;age["john"]=35;for(i in age){print i,age[i]}}'               #age=(tom:22 bob:18 john:35)
john 35
tom 22
bob 18
[root@SHELL ~]# 
​
#awk数组应用
[root@SHELL ~]# scp 192.168.4.250:/var/log/httpd/access_log /root/shell/day05/
​
#初始化数组,所有IP地址在处理前都出现了0次
[root@SHELL ~]# awk 'BEGIN{print "IP地址\t次数";IP[$1]=0} {IP[$1]=IP[$1]+1} END{for(ip in IP){print ip"\t"IP[ip]}}' /root/shell/day05/access_log 
​
​
[root@SHELL ~]# awk 'BEGIN{print "IP地址\t次数"} {IP[$1]++} END{for(ip in IP){print ip"\t"IP[ip]}}' /root/shell/day05/access_log 
IP地址  次数
192.168.8.154   33
192.168.8.155   60
192.168.8.156   30
192.168.8.170   3
192.168.8.157   68
[root@SHELL ~]# awk 'BEGIN{print "IP地址\t次数"} {IP[$1]=IP[$1]+1} END{for(ip in IP){print ip"\t"IP[ip]}}' /root/shell/day05/access_log 
​
​
​
​
##格式:
awk 'BEGIN{print 表头}   {A[$n]++}    {for(i in A){print i,A[i]}}'   file
​
[root@SHELL ~]# awk 'BEGIN{print "资源\t次数"}   {A[$7]++}    {for(i in A){print i,A[i]}}' /root/shell/day05/access_log 
[root@SHELL ~]# who | awk 'BEGIN{print "用户名\t次数"}   {A[$1]++}    {for(i in A){print i,A[i]}}'
用户名  次数
root 1
root 2
[root@SHELL ~]# 

五、awk变量

[root@SHELL ~]# a=1
[root@SHELL ~]# echo $a
1
[root@SHELL ~]# awk 'BEGIN{print a}'
​
[root@SHELL ~]# awk 'BEGIN{print $a}'
​
[root@SHELL ~]# awk "BEGIN{print $a}"
1
[root@SHELL ~]# awk -v tmp=$a 'BEGIN{print tmp}'
1
​
[root@SHELL ~]# who | awk '{print $1}'
root
root
[root@SHELL ~]# who | awk "{print $a}"
1
1
[root@SHELL ~]# who | awk -v tmp=$a '{print $tmp}'
root
root
[root@SHELL ~]# who | awk "{print \$$a}"
root
root
[root@SHELL ~]# 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值