shanjayp
shanjayp
Published on 2025-02-14 / 4 Visits
0
0

4.Shell四剑客之sed与awk

shell四剑客:

  • grep:主要的功能可以实现对文件的内容进行模糊搜索

  • find:主要的功能可以实现对系统中文件所在路径进行查找

  • sed:功能跟vim一样的,主要对文件的内容进行一些增删改查等操作

  • awk:功能与grep类似,主要的作用可以对文件的内容进行模糊搜索,但是可以搜索某一列!

sed文本编辑器

sed是一个非交互的文本编辑器,实现的功能跟vim相同,主要是对文件内容进行输出、删除、替换、复制、剪切、导入、导出等功能

命令格式1:前置命令 | sed [选项] '[指令]' 文件名

命令格式2:sed [选项] '[指令]' 文件名

  • 常用选项:

    • -n #屏蔽默认输出,默认sed会将所有的输出结果输出到屏幕中,-n只把sed处理的行输出到屏幕

    • -i #直接修改文件内容,如果不加-i选项,并不会真正改变文件的内容

    • -r #支持扩展正则表达式的符号

  • 动作指令:

    • p #输出指定的行,如:2,4p 输出第234行,如:2p;4p 打印第2行与第4行

    • d #删除指定的行,如:2,4d 删除第234行,如:2d;4d删除第2行与第4行

    • s #字符串替换,如:s/旧内容/新内容/ (使用该指令时,不要加p指令)

#打印文件第一行内容
sed -n '1p' /etc/passwd
​
#打印文件第三行内容
sed -n '3p' /etc/passwd
​
#打印文件第3行到6行
sed -n '3,6p' /etc/passwd
​
#打印文件第3行到6行
head -6 /etc/passwd | tail -4
​
#利用正则表达式符号匹配以root开头的行(正则表达式符号要放在//内)
sed -n '/^root/p' /etc/passwd
​
#匹配以bash结尾的行
sed -n '/bash$/p' /etc/passwd
sed -n '/nologin$/p' /etc/passwd
​
#=号用于显示行号,例如:打印文件最后一行,打印行号
sed -n '$=' /etc/passwd
​
#打印以root开头的行号
sed -n '/^root/=' /etc/passwd
​
#拷贝文件练习
cp /etc/passwd /opt/test
​
​
#使用i选项直接修改源文件
sed -i '2,4d' test 
​
#使用分号分隔
sed -i '10d;12d' test
​
​
#空行
sed  -n '/^$/p' /etc/fstab
​
#准备素材
sed -n p num.txt
2021 2020 2019 2018
2021 2021 2020 2019
2021 2022 2021 2020
​
#替换文件每一行匹配到的第一个字串
sed -n 's/2021/xxxx/p' num.txt 
​
#真正修改文件内容是,不要加p打印(否则会在将打印的内容写入到文件中)
sed -i 's/2021/xxxx/' num.txt
​
#替换文件每一行匹配到的第二个字串
sed 's/2021/xxxx/2' num.txt 
sed -n 's/root/xxxx/2' test
root:x:0:0:xxxx:/root:/bin/bash
​
sed -n 's/root/xxxx/3' test
root:x:0:0:root:/xxxx:/bin/bash
​
#替换文件每一行匹配到的所有指定字串
sed -n 's/root/xxxx/g' test
xxxx:x:0:0:xxxx:/xxxx:/bin/bash
​
#将匹配到的第一个字串替换成空
sed 's/2021//' xx.txt 
​
#将匹配到的第=二字串替换成空
sed -n 's/root//2' test
root:x:0:0::/root:/bin/bash
​
sed -n 's/root//3' test
root:x:0:0:root:/:/bin/bash
​
#替换符可以使用任意的特殊符号
sed -n 's#root##' test
​
#将文件中/bin/bash替换成/sbin/nologin
sed -n 's/\/bin\/bash/\/bin\/sh/g' test
sed -n 's,bin/bash,sbin/nologin' test
​
#使用sed给文件1-3行批量添加注释
sed -n '1,3s/^/#/p' test
sed -i '1,3s/^/#/' test
sed -n '1,3p' test
​
#批量去除1-3行的注释
sed -n '1,3s/^#//' test
sed -i '1,3s/^#//' test
sed -n '1,3p' test
​
#将文件中所有的数字替换成空
sed -n 's/[0-9]//g' test
​
#将文件中所有的英文字母替换成空
sed -n 's/[a-Z]//g2' test

awk文本处理工具

awk是一个文本处理工具,功能类似于grep,但是比grep要更加的强大,支持对文件内容的列进行过滤。

awk过滤数据时支持仅打印某一列,如:第2列、第4列...

awk命令格式1:awk [选项] '条件1{指令} 条件2{指令}' 文件名

awk命令格式2:前置命令 | awk [选项] '条件{指令}'

常用指令:print 是最常用的打印指令

常用选项:-F #指定分隔符,如不指定分隔符,默认以空格或tab键为默认分隔符,可通过[]集合匹配多种单个字符

awk内置位置变量:$1第一列,$2第二列,$3第三列,依次类推,NR文件当前行号,NF文件当前列数

命令格式1示例:提示awk使用双引号会出现语法错误

#手动指定以:作为分隔,打印文件第一列
awk -F: '/root/ {print $1}' test
​
#打印文件第一列和第七列(默认没有空格与tab键作为分隔符,打印文件所有内容)
awk -F: '/root/ {print $1,$7}' test
​
#通过[]集合匹配多种单个字符作为分隔符,打印用户名与解释器字段
awk -F[:/] '{print $1,$10}' test
​
#通过正则表达式过滤以root开头的行
awk -F: '/^root/{print}' test
​
#通过正则表达式过滤以root开头的行,打印第1列与第7列
awk -F: '/^root/ {print $1,$7}' test
​
#打印文件每一行与每一行的列数,NR文件当前行号,NF文件当前列数
awk -F: '{print NR,NF}' test
​
#打印文件每一行与每一行的列数,并打印最后一列
awk -F: '{print NR,NF,$NF}' test
​
#通过常量打印执行的列
awk -F: '{print "用户名:"$1,"\t""解释器:"$NF}' test
​
#匹配第一列包含root的行
awk -F: '$1~/root/ {print $1,$7}' test
​
#匹配第一行,并打印某一列
awk -F: 'NR~1,/2023/ {print $3}' test
​
#排除第7列noloogin的行,打印第1列与第7列
awk -F: '$7!~/nologin/{print $1,$7}' /etc/passwd
​
#利用扩展正则过滤,以root或者adm开头的行,打印第1列与第7列
awk -F: '/root|adm/{print $1,$7}' /etc/passwd

awk使用数值/字符串比较设置条件

  • 等于: ==

  • 不等于: !=

  • 大于: >

  • 大于等于: >=

  • 小于: <

  • 小于等于:<=

#打印行号等于3,并指定列数
awk 'NR==3{print $2}' test
​
#打印文件中第3列大于等于1000,打印第1列,第3列,第7列
awk -F: '$3>=1000{print $1,$3,$7}' /etc/passwd
​
#打印文件中第三列小于1000,打印第1列,第3列,第7列
awk -F: '$3<1000{print $1,$3,$7}' /etc/passwd
​
#打印文件中第3列大于500并且小于1000,打印第1列,第3列,第7列
awk -F: '$3>500 && $3<1000 {print $1,$3,$7}' /etc/passwd
​
#打印第一列不等于root的行
awk -F: '$1!="root"{print}' /etc/passwd

awk完整命令格式:awk ‘BEGIN{指令} {指令} END{指令}’ 文件名

  • BEGIN{指令} #读取文件内容之前执行指令,指令执行一次,行前处理

  • {指令} #读取文件过程中执行,指令逐行执行,读一行,执行一次

  • END{指令} #读取文件内容结束后执行指令,指令执行一次,行后处理

#BEGIN{指令}行前处理
awk 'BEGIN{print "正在处理中"}'
正在处理中
​
#通过awk统计系统里使用bash解释器的用户个数?
awk 'BEGIN{x=0}/bash$/{x++}END{print x}' /etc/passwd
awk '/bash$/{x++}END{print x}' /etc/passwd

awk分支结构

  • if单分支格式:if(条件){指令}

  • if双分支格式:if(条件){指令}else{指令}

#if单分支统计passwd文件中UID大于或等于1000的用户个数
awk  -F: '{if($3>=1000){num++}} END{print num}' /etc/passwd
​
#if双分支统计passwd文件中UID大于等于1000的用户,和小于1000的用户个数
awk -F: '{if($3>=1000){num1++} else{num2++}} END{print num1,num2}' /etc/passwd

awk数组

  • 定义数组格式1:数组名[下标]=值

  • 定义数组格式2:数组名=值

  • 数组的用法:for(变量名 in 数组名) {print 数组名[变量]}

#awk定义数组方式
awk 'BEGIN{x[0]=10;x[1]=20;print x[0],x[1]}'
​
#awk定义数组方式
awk 'BEGIN{x[0]++;print x[0]}'

awk循环结构

  • 命令格式:for(变量名 in 数组名){print 数组名[变量]}

awk 'BEGIN{a[0]=00;a[1]=11;a[2]=22;for(i in a){print i,a[i]}}'

awk命令格式2:前置命令 | awk [选项] '条件{指令}'

#通过awk打印剩余内存
free -h | grep Mem | awk '{print $4}'
free -h | awk '/Mem/{print $4}'
​
#用awk写一个监控脚本,监控网卡的进出口流量
vim while_liuliang.sh 
#!/bin/bash
while :
do
        clear
        ifconfig ens32 | awk '/inet /{print "IP:",$2}'
        ifconfig ens32 | awk '/RX p/{print "入口流量:",$6,$7}'
        ifconfig ens32 | awk '/TX p/{print "出口流量:",$6,$7}'
        sleep 0.1
done
​
​
#使用awk过滤系统根分区使用情况
df -h / | awk '/\/$/{print $4}'
df -h / | awk '/\/$/{print $4}' | awk -FG '{print $1}'
​
​
#过滤根分区剩余空间与物理内存空间
vim df_free.sh
#!/bin/bash
df -h | grep '/$' | awk '{print "根分区剩余空间:",$4}'
free -h | grep Mem | awk '{print "物理内存剩余空间:", $4}'
​
#通过awk统计用户当前登录的终端数量
who | awk '{ip[$1]++}END{for(i in ip)print i,ip[i]}'

问题:如何把小括号去除掉???

[root@test script]# ifconfig ens32 | awk  '/RX packets/ {print $6,$7}' 
(1.3 MiB)



Comment