awk命令学习

一、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
相关推荐
我言秋日胜春朝★1 分钟前
【Linux】冯诺依曼体系、再谈操作系统
linux·运维·服务器
努力的家伙是不讨厌的4 分钟前
解析json导出csv或者直接入库
开发语言·python·json
云空26 分钟前
《Python 与 SQLite:强大的数据库组合》
数据库·python·sqlite
饮啦冰美式32 分钟前
22.04Ubuntu---ROS2使用rclcpp编写节点
linux·运维·ubuntu
wowocpp32 分钟前
ubuntu 22.04 server 安装 和 初始化 LTS
linux·运维·ubuntu
Huaqiwill34 分钟前
Ubuntun搭建并行计算环境
linux·云计算
wclass-zhengge36 分钟前
Netty篇(入门编程)
java·linux·服务器
Lign1731438 分钟前
ubuntu unrar解压 中文文件名异常问题解决
linux·运维·ubuntu
凤枭香1 小时前
Python OpenCV 傅里叶变换
开发语言·图像处理·python·opencv