一、awk
简述
awk
:最主要功能:按行取列
awk
默认的分隔符:空格和tab
键,多个空格会自动压缩。
awk
的工作原理:根据指定信息,逐行读取文本内容,然后按照条件进行格式化输出。
二、awk
用法
2.1 awk
命令
选项:
-F
:指定分隔符,默认就是空格-v
:变量复制
内置变量:
-
$#
:#是数字,表示按行需要取出的第几个字段 -
$0
:打印所有,展示整行内容 -
NR
:需要处理的行号 -
NF
:处理行的字段字数,特殊的,$NF
表示当前行的最后一个字段 -
FS
:和F
一样,都是指定分隔符,比如指定:
为分隔符:-F:
或者FS=":"
-
OFS
:指定输出内容的分隔符 -
RS
:行分隔符,可以根据RS的设置把文件内容分割成多个记录,也可以改变行的分隔符,默认是\n
,回车,换行。
2.2 命令格式
bash
awk -F '操作符 {动作 处理对象}'
-F
:指定分隔符,如果是空格可以不加动作
:默认就是打印,print
例:
打印行号
bash
awk '{print NR}' filename
打印行号和文本内容
bash
awk '{print NR,$0}' filename
打印指定行,如第三行
bash
awk 'NR==3{print}' filename
打印第三行以后得行
bash
awk 'NR>3{print}' filename
打印第三行到第五行
bash
awk 'NR==3,NR==5{print}' filename
打印第三行和第五行
bash
awk 'NR==3;NR=5{print}' filename
打印偶数行
bash
awk 'NR%2==0{print}' filename
打印奇数行
bash
awk 'NR%2==1{print}' filename
取出/etc/passwd里的每行第三个字段
bash
awk -F: 'print{$3}' /etc/passwd
过滤/etc/passwd里含有root的行,一般很少用awk
过滤文本
bash
awk -F: '/root/{print}' /etc/passwd
2.3 BEGIN
打印模式
bash
awk 'BEGIN{预先条件};{处理条件};END{结束条件}'
预先条件
:执行awk
命令前的初始化操作
处理条件
:如何对初始值进行操作
结束条件
:处理完之后的操作,一般都是打印
END不是总是需要的,只写BEGIN也可以,比如做一次性操作的计算等
例:有初始条件的操作
bash
awk 'BEGIN{x=0};{x++};END{print x}' filename
解释:根据filename
文件的行数,对变量x
执行++
,最后打印出来的就是文件的行数
例:一次性操作
计算10*2
bash
awk 'BEGIN{print 10*2}'
计算2的5次方(幂运算)
bash
awk 'BEGIN{print 2**5}'
awk 'BEGIN{print 2^5}'
2.4 变量复制
-v
:变量复制,把外部变量的值复制到awk
命令内部
例:
bash
vim test1.sh
a=3
b=4
num=$(awk 'BEGIN{print a+b}')
echo $num
执行test1.sh
脚本,发现输出结果为0
bash
sh test1.sh
0
这是因为awk
命令的内部变量和全局变量隔离,外部的变量没有传进awk
命令中去,对test1.sh
做如下修改
bash
num=$(awk -v a="$a" -v b="$b" 'BEGIN{print a+b}')
bash
sh test1.sh
7
如此,才把外部变量传到awk
命令内部去
2.5 条件判断
例:
获取/etc/passwd中第三列UID大于999的用户所在的行
bash
awk -F: '$3>999 {print $0} ' /etc/passwd
获取/etc/passwd中第三列UID等于1000的用户所在的行
bash
awk -F: '$3==1000 {print $0} ' /etc/passwd
注:不能用=
,用=会直接赋值,而不是判断
2.6 awk
的三元表达式
实际就是一个if...else...
语句
bash
awk -F: '{num=($3>$4)?$3:$4;{print num;$0}}' /etc/passwd
解释:num=($3>$4)?$3:$4;
num
是定义的变量,将后面判断后得到的结果赋给变量num
($3>$4)?
:相当于if [ $3 > $4 ]
,后面的内容就是为真的时候输出的内容,这里是输出$3
第一个:
:相当于else
,后面的内容就是判断为假的时候输出的内容,这里是输出$4
后一个;
:相当于fi
2.7 awk
的精确筛选
bash
$n(> < ==)用于比较数值
$n~"字符串" :该字段包含这个字符串
$n!~"字符串" :该字段不包含这个字符串
$n=="字符串" :该字段等于这个字符串
$n!="字符串" :该字段不等于这个字符串
$NF :最后一个字段
例:打印/etc/passwd
第七列包含bash这个字段的行,取行的第一列和最后一列
bash
awk -F: '$7~"bash" {print $1,$NF}' /etc/passwd
print
列的时候不能范围取列,要想打印多个列,必须列出所有要打印的列,用,
隔开
打印/etc/passwd第七列字段为/bin/bash
的行,取行的第一列和最后一列
bash
awk -F: '$7=="/bin/bash" {print $1,$NF}' /etc/passwd
解释:使用==
时,匹配的内容必须和字段内容完全一致
去除/var/log/messages 文件前5行 第5列的内容
bash
head -5 /var/log/messages | awk '{$5=""}1'
解释:awk '{$5=""}1',表示对于每一行,将第5列设为空(即清空第5列),然后打印整行。1
是一个条件,表示打印处理后的结果。
2.8 awk
的"且"、"或"条件
且:&&
;或:||
例:打印/etc/passwd
第一列为root
且 第七列(最后一列)为/bin/bash
的行
bash
awk -F: '($1=="root")&&($NF=="/bin/bash") {print $0}' /etc/passwd
# && 两边的条件的()可以不加,但加了更方便阅读
打印/etc/passwd
第一列为dhcp
或 第七列为/bin/bash
的行
bash
awk -F: '($1=="dhcp")||($NF=="/bin/bash") {print $0}' /etc/passwd
2.9 awk
做小数运算
awk
做小数运算,有几位小数就算几位小数,也可以指定输出结果的小数位数
例:
bash
awk 'BEGIN{printf "%.#f" , 小数运算}'
# {}里的%.#f号表示数字,数字是几就表述输出结果有几位小数,四舍五入
awk 'BEGIN{printf "%.F" , 小数运算}'
# %.F 表示输出结果为整数,四舍五入
2.10 附加内容
curl
命令
curl
是一个功能强大的命令,可以获取和发送数据
格式:
bash
curl 域名
curl IP地址
-O
:下载文件到本地
-o
:将文件下载到指定路径
-x
:发送post请求
-i
:可以获取web软件的版本(前提是服务端没有隐藏版本号)
2.11 练习
例1:host.txt
文件的内容为
1 www.kgc.com
2 mail.kgc.com
3 ftp.kgc.com
4 linux.kgc.com
5 blog.kgc.co
获取其中的所有子域名(www mail ftp 等 )
bash
cat host.txt | awk -F'[ .]+' '{print $2}'
解释:-F'[ .]+'
表示以空格或 .
作为分隔符,
例2:使用awk
获取 /etc
目录下所有文件的总大小
bash
ll /etc | awk '/^-/{print sum+=$5} END{print "文件的总大小:"sum/1024"M" }'
解释:ll
查看的结果,文件以-
开头,文件大小在第5列,把文件大小累加到变量sum,输出sum
例3:监控内存,cpu和硬盘的根目录,超过80%提示用户,写成函数库的行,每天早上 的8:50分,执行一次脚本。
监控各个负载的功能使用函数库的形式实现
函数库文件:testlib.sh
bash
# 检测CPU负载
cputest () {
local c=$(top -b -n 1 | awk 'NR==3 {printf "%.F", $2+$4}')
if [[ c -ge 80 ]];then
echo "当前CPU负载${c}%,超过80%!请及时处理!"
else
echo "CPU负载正常,当前负载${c}%"
fi
}
# 检测内存负载
memtest () {
local b=$(free -m | awk 'NR==2 {printf "%.F", $3/$2*100 }')
if [[ $b -ge 80 ]];then
echo "当前内存负载${b}%,超过80%!请及时处理!"
else
echo "内存负载正常,当前负载${b}%"
fi
}
# 检测根目录负载
blktest () {
local a=$(df -h | awk '$NF=="/" {print $5}' | tr -d "%")
if [[ $a -ge 80 ]];then
echo "根目录当前使用达到${a}%,超过80%!请及时处理!"
else
echo "根目录使用空间正常,当前已使用${a}%"
fi
}
每天执行的脚本文件jiankong.sh
bash
. /opt/zuoye1/testlib.sh
cputest
memtest
blktest
创建定时任务
bash
crontab -e
50 8 * * * /opt/zuoye1/jiankong.sh
查看定时任务
bash
crontab -l
50 8 * * * /opt/zuoye1/jiankong.sh