(转)awk 详解
出处:https://blog.51cto.com/yijiu/1358416
awk详解
awk是一款非常牛逼的报告生成工具,能够将文本格式化成显示为比较直观的结果
废话不多说,直接上例子
awk的内置变量
FS: field separator,读取文件本时,所使用字段分隔符;
RS: Record separator,输入文本信息所使用的换行符;
OFS: Output Filed Separator: 输出的字段、其与print命令的最大不同是,printf需要指定format;
2、format用于指定后面的每个item的输出格式;
3、printf语句不会自动打印换行符;\n
format格式的指示符都以%开头,后跟一个字符;如下:
%c: 显示字符的ASCII码;
%d, %i:十进制整数;
%e, %E:科学计数法显示数值;
%f: 显示浮点数;
%g, %G: 以科学计数法的格式或浮点数的格式显示数值;
%s: 显示字符串;
%u: 无符号整数;
%%: 显示%自身;
修饰符:
N: 显示宽度;
-: 左对齐;
+:显示数值符号;
#打印第1列和第3列,并使用修饰符:字符距离为15,类型为整数型并将其换行显示,如果不加参数\n 那么打印出的信息则全显示在一行中
[root@test3 ~]# awk -F: '{printf "%-15s%i\n",$1,$3}' /etc/passwd | head -5
root 0
bin 1
daemon 2
adm 3
lp 4
这里面有2个符号 一个是s% 一个是 i% s%表示显示的是字符串 i%表示显示为十进制的整数 %-15s %i\n 表示使用多宽的字符来显示它 -号表示左对齐
不使用右对齐
[root@test3~]# awk -F: '{printf "%15s %i\n",$1,$3}' /etc/passwd | head 2
root 0
bin 1
显示无符号整数:
[root@test3~]# awk -F: '{printf "%15s %u\n",$1,$3}' /etc/passwd
要点:
1、各项目之间使用逗号隔开,而输出时则以空白字符分隔;
2、输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式;数值会先转换为字符串,而后再输出;
3、print命令后面的item可以省略,此时其功能相当于print $0, 因此,如果想输出空白行,则需要使用print"";
awk的操作符
·算数操作符
-x: 负值
+x: 转换为数值;
x^y:
x**y: 次方
x*y: 乘法
x/y:除法
x+y:
x-y:
x%y:
·字符串操作符:
只有一个,而且不用写出来,用于实现字符串连接;
·赋值操作符:
=
+=
-=
*=
/=
%=
^=
**=
++
--
需要注意的是,如果某模式为=号,此时使用/=/可能会有语法错误,应以/[=]/替代;
·布尔值
awk中,任何非0值或非空字符串都为真,反之就为假;
·比较操作符:
x <y True ifx is less than y.
x <= y Trueif x is less than or equal to y.
x > y Trueif x is greater than y.
x >= y Trueif x is greater than or equal to y.
x == y Trueif x is equal to y.
x != y Trueif x is not equal to y.
x ~ y Trueif the string x matches the regexp denoted by y.
x !~ y Trueif the string x does not match the regexp denoted by y.
subscript in array True if the array array hasan element with the subscript subscript.
·表达式间的逻辑关系符:
&&
||
比如:
#如果第3列的数值大于400 并且第7列匹配bash字符串那么打印1 3 7列 并修饰
[root@test3~]# awk -F ':' '$3>400 &&$7~/bash/{printf "%-15s %i %s\n",$1,$3,$7}' /etc/passwd
test 500 /bin/bash
test2 501 /bin/bash
mysql 498 /bin/bash
mockbuild 502 /bin/bash
awk常用分隔符
一般常用分隔符分为两类:
(1)字段分隔符:某行中如何区分不同的列
(2)行分隔符:默认情况下就是换行符,完全指定别的分割符为换行符,这样可以将一行当多行或 多行当一行来处理
所以一般来将字段分隔符的输入分割符,我们被称为FS,而FS恰好就是awk内置变量
上面已经介绍了awk的内置变量FS和OFS的使用,接下来我们来回顾一下
FS:指定输入字段分隔符
#指定以冒号为分割符号,打印列首和列尾
[root@test3~]# awk 'BEGIN{FS=":"} {print $1,$NF}' /etc/passwd | head -3
root/bin/bash
bin/sbin/nologin
daemon/sbin/nologin
OFS:指定输出字段分割符
#指定以冒号为分割符号,指定##为默认输出分割符(这里不再是空格),打印列首和列尾
[root@test3~]# awk 'BEGIN{FS=":";OFS="##"} {print $1,$NF}' /etc/passwd| head -3
root##/bin/bash
bin##/sbin/nologin
daemon##/sbin/nologin
NF
#引用变量本身的值是不可以加$的 这里加$是因为用变量本身的函数再补以$符号
[root@test3~]# df -h | awk 'BEGIN {print "fliesystem mount" } {print $1,$NF}'
加$符号,打印出的结果,筛选为第5列
[root@test3~]# awk -F ':' 'BEGIN{TEST=5} {print $TEST}' /etc/passwd | head -5
root
bin
daemon
adm
lp
再将$符号去掉可以看到只将TEST赋予的值打印了出来
[root@test3~]# awk -F ':' 'BEGIN{TEST=5} {print TEST}' /etc/passwd | head -5
5
5
5
5
5
控制语句
if-else
语法:if(condition) {then-body} else ` else-body `
我们可以使用单分支if语句 只有if没有else
#判断,如果这个用户的id号是否为0,如何是0则输出为管理员反之并打印其用户名
[root@test3~]# awk -F: '{if($3==0){print $1,"admin"}else{print$1,"user"}}' /etc/passwd | head -3
rootadmin
binuser
daemonuser
使用修饰符
[root@test3~]# awk -F: '{if($3==0){printf "%-15s%s\n",$1,"admin"}else{printf "%-15s %s\n",$1,"user"}}' /etc/passwd | head -3
root admin
bin user
daemon user
用户的自定义变量
参数:-v
#如果用户的id号大于等于500那么使变量在其自身+1次并打印,最终所有大于500的用户的个数的和
#print必须写在END后面,不然会依次显示行的处理结果
[root@test3~]# awk -F: -v sum=0 '{if($3>500) sum++} END {print sum}' /etc/passwd
2
这里sum没有加$,因为$显示的变量值是对应的字段的值,如下所示:
[root@test3~]# awk -F: -v sum=0 '{if ($3>500) sum++} END{print $sum}'/etc/passwd
x
分别打印id大于500的用户名
[root@test3~]# awk -F: '{if ($3>=500) print $1}' /etc/passwd
test
test2
mockbuild
使用awk统计登录失败的ssh登录信息
#首先找到关键字,其实用grep+管道+awk更直观一些,这里为了练习就全部都用awk了
#看到有3行此类信息,然后对其统计有多少条匹配的信息
[root@test3~]# awk '/Failed/' /var/log/secure
Feb 1116:48:40 test3 sshd[2015]: Failed password for invalid user adad from 10.0.10.1port 58136 ssh2
Feb 1116:48:44 test3 sshd[2015]: Failed password for invalid user adad from 10.0.10.1port 58136 ssh2
Feb 1116:48:47 test3 sshd[2015]: Failed password for invalid user adad from 10.0.10.1port 58136 ssh2
#使用-v声明变量值为0,{sum++}必须单独在一{..}模块中,在结尾处打印变量
[root@test3~]# awk -v sum=0 '/Failed/ {sum++} END {print sum}' /var/log/secure
3
筛选web日志文件,并且将以GET请求后缀名是以.html结尾的行进行访问数统计
[root@test3logs]# awk '{if($7 ~ "html$")print $0}' access_www.test.com.log-20140209
10.0.10.1- - [04/Feb/2014:10:40:07 +0800] "GET /1.html HTTP/1.1" 200 6
10.0.10.1- - [04/Feb/2014:10:40:11 +0800] "GET /2.html HTTP/1.1" 200 5
10.0.10.62- - [04/Feb/2014:10:40:37 +0800] "GET /1.html HTTP/1.1" 200 6
10.0.10.62- - [04/Feb/2014:10:40:41 +0800] "GET /2.html HTTP/1.1" 200 5
10.0.10.62- - [04/Feb/2014:10:40:45 +0800] "POST /2.html HTTP/1.1" 200 5
10.0.10.62- - [04/Feb/2014:10:40:51 +0800] "POST /1.html HTTP/1.1" 200 6
10.0.10.1- - [04/Feb/2014:10:48:22 +0800] "GET /1.html HTTP/1.1" 200 6
可以看到一共有7行,下面来使用awk来统计其访问量
[root@test3logs]# awk -v sum=0 '{if($7 ~ "html$") sum++} END {print sum}'access_www.test.com.log-20140209
7
循环
while循环
主要功能在切片后每一个字段中进行循环
语法:while (condition) {statement1;statement2;...}
#显示没行的前三段
[root@test3logs]# awk -F: '{i=1;while (i<=3) {print $i;i++} }'/etc/passwd | head -6
root
x
0
bin
x
1
#引用变量不需要加$
#每个处理结果都是一行,所以是按行输出的
#如果不想让其按行输出则:
[root@test3logs]# awk -F: '{i=1; while(i<=3) {printf "%s ", $i;i++};{printf"\n"} }' /etc/passwd
awk内置函数length
length能取出指定字符的长度
#显示每行中数字大于等于100的数字
[root@test3~]# cat hello.txt
111 11 234 99 87
130 8328 91
2384842 84 671 24
87 62 1992
#之所以使用i<=NF是因为每个字段的数值是不一样的,但是这里每一列的个数都不一样的,为的目的是便利每一行的每一列
[root@test3~]# awk '{i=1;while (i<=NF) {if($i>=100) print $i;i++ }}' hello.txt
111
234
130
2384
842
671
1992
do-while 循环
其与while区别在于 while有可能一开始就不会循环,因为条件不满足
而do-while则不管值为真假(不管条件满足与否,至少先执行一次循环),先进行循环
语法: do {statement1, statement2, ...} while (condition)
awk -F:'{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd
awk -F:'{i=4;do {print $i;i--}while(i>4)}' /etc/passwd
for循环
语法 : for (variable assignment; condition iteration process ) {statement1 ... }
#以冒号为分割符,显示每行的前三列,与上面的while循环的结果是一样的
[root@test3~]# awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd | head -10
root
x
0
bin
x
1
daemon
x
2
使用内置函数length
#awk-F: '{for(i=1;i<=NF;i++) { if (length($i)>=4) {print $i}}}' /etc/passwd
使用for循环来查找这个文件中大于等于100的数字
#一定让i小于NF,如果$i大于等于100 那么现实$i
#大致意思为我们要读取这个文件的每一行,而后进行每一列进行判断,而for是对其进行每一列来进行循环的,if为判断每一列只要大于其值则打印
[root@test3~]# awk '{for(i=1;i<=NF;i++) {if ($i>=100) print $i}}' hello.txt
111
234
130
2384
842
671
1992
数组
#数组为一组连续的课存多个值内存空间
#使用数组索引(下标)
#例:
bash:
arry=('mon''tue' 'wed')
arry[2]
这里的arry[2]就为数组的索引,但是bash4之后还支持关联数组:
索引下标可以非数组,可以自定义下标:
arry=(a='mon'b='tue')
aryy[b]
而awk是支持所谓的关联数组的
for能够去便利数组元素:
语法: for (i in array) {statement1,statement2, ... }
统计passwd文件最后一列出现的次数
[root@test3~]# awk -F: '$NF!~/^$/{BASH[$NF]++}END{for (A in BASH) {printf"%-15s:%i\n" ,A,BASH[A]}}' /etc/passwd
/sbin/shutdown:1
/bin/bash :5
/sbin/nologin :22
/sbin/halt :1
/bin/sync :1
#首先$NF 为最后一个字段
#!~为不匹配,这里不为空
#如果最后一列不为空,则将其值取出并对其做匹配:
BASH[] 为数组 那么BASH[NF]为数组索引,可以将最后一个字段的字段本身,将其作为下标
比如:
最后一列为 /bin/bash,那么将其做为BASH的下标
所以会出现这样结果:
BASH[/bin/bash]
BASH[/sbin/nologin] 用它来做下标即为另一个元素,那么这个元素中存放的是什么也没有声明
所以这里BASH[$NF]++ 使其自身自动加值,一般初始值是0,所以 它的意思为 如果不为空,则BASH[NF]++ :
当我们读了第一行之后意味着BASH[/bin/bash]的元素为=1 ,
再读取第二行于是又一个新元素其BASH[/sbin/nologin]的值=1
再读取第三行,筛取最后一列为/sbin/nologin其 BASH[/sbin/nologin]的值+1=2
继续。。。每一次都往上累加
#
{print "%15s:%i\n",A,BASH[A]}}
#显示了A,再显示了BASH[A]
A是字符串
BASH[A]为元素的值
得出的结果为:
/bin/bash : 1
/sbin/nologin:1 ....
#使用netstate -tanl查看网络状态并统计每种状态的值
[root@test3~]# netstat -tanl | awk '/^tcp/{sum[$NF]++} END {for (i in sum) {printi,sum[i]}}'
TIME_WAIT61
ESTABLISHED3
LISTEN8
语法说明:
awk /^tcp/{动作} #将tcp协议开头的行筛选并打印出来
awk /^tcp/{sum[$NF]} #$NF的值一定是字符串本身
awk /^tcp/{sum[$NF]++} #第一次状态值为1 第二次为2 以此类推
#for(下标 in 数组)
awk/^tcp/{sum[$NF]++}END{for(i in sum)} #使用for循环,会便利数组的下标,所以我们显示的是
awk/^tcp/{sum[$NF]++}END{for(i in sum) print i,sum[i]}' #i是字符串本身,sum[i] 数组的以i为下标的数组的值
所以得出的结果为:
[root@test3~]# netstat -tanl | awk '/^tcp/{sum[$NF]++} END {for (i in sum) {printi,sum[i]}}'
ESTABLISHED3
LISTEN8
统计当前系统上的日志access.log 每一个ip发起过多少次请求
[root@test3logs]# awk '{ip[$1]++} END {for(i in ip) print i,ip[i]}'access_www.test.com.log
127.0.0.161
next
提前结束对本行文本的处理,并接着处理下一行;例如,下面的命令将显示其ID号为奇数的用户:
[root@test3logs]# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd
bin 1
adm 3
sync 5
halt 7
operator11
gopher13
nobody99
dbus 81
vcsa 69
abrt173
saslauth499
postfix89
named25
test2501
awk内置函数
语法:split(string, array [,fieldsep [, seps ] ])
功能:将string表示的字符串以fieldsep为分隔符进行分隔,并将分隔后的结果保存至array为名的数组中;数组下标为从1开始的序列;
[root@test3logs]# netstat -tan | awk'/:80\>/{split($5,clients,":");ip[clients[4]]++}END{for(a in ip)print ip[a],a}' | sort -rn | head -50
9010.0.10.62
1 *
语法说明:
awk '/:80\>/
{split($5,clients,":"); #当我们取得第五列的时候,将第五列以冒号作为分割(":" 为分隔符),保存在名为clients的变量中,意味着clients1保存的是我们的ip地址,clients2保存的是端口号.....
IP[clients[1]]++} #ip地址+1
END{for(i in IP) #便利每个IP显示的次数
{print IP[i],i}}' #先显示次数再显示地址
筛取硬盘空间使用比例大于20%
[root@test3logs]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 20G 13G 5.3G 72% /
tmpfs 498M 0 498M 0% /dev/shm
/dev/sda1 194M 45M 140M 25% /boot
/dev/mapper/myvg-mydata
5.0G 170M 4.6G 4% /mydata
[root@test3logs]# df -hl | awk'!/File/{split($5,percent,"%");if(percent[1]>=20) {print $1}}'
/dev/sda3
/dev/sda1
(转)awk 详解的更多相关文章
- 【linux】linux命令grep + awk 详解
linux命令grep + awk 详解 grep:https://www.cnblogs.com/flyor/p/6411140.html awk:https://www.cnblogs.com ...
- awk详解 数组
第1章 awk命令基础 1.1 awk命令执行过程 1.如果BEGIN 区块存在,awk执行它指定的动作. 2.awk从输入文件中读取一行,称为一条输入记录.如果输入文件省略,将从标准输入读取 3.a ...
- Linux下Awk详解(转载)
什么是Awk Awk是一种小巧的编程语言及命令行工具.(其名称得自于它的创始人Alfred Aho.Peter Weinberger 和 Brian Kernighan姓氏的首个字母).它非常适合服务 ...
- awk详解
一.简介 强大的文本分析工具,基于指定规则浏览和抽取信息.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理.awk有3个不同版本: awk.nawk和ga ...
- linux脚本Shell之awk详解(二)
三.printf的使用 print format 生成报表 %d 十进制有符号整数 %u 十进制无符号整数 %f 浮点数 %s 字符串 %c ...
- linux脚本Shell之awk详解
一.基本介绍1.awk: awk是一个强大的文本分析工具,在对文本文件的处理以及生成报表,awk是无可替代的.awk认为文本文件都是结构化的,它将每一个输入行定义为一个记录,行中的每个字符串定义为一个 ...
- 5_find grep sed awk 详解
find :查找文件系统中指定的文件.可以按文件名(-name) 权限(-perm) 归属人 查找. find 要查找文件的路径 表达式 *通配符 可以添加在文件名的任意位置 常用的例子( ...
- awk 详解+实例
1. awk简介 awk是一种编程语言,用于在linux/unix下对文本和数据进行处理.数据可以来自标准输入.一个或多个文件,或其它命令的输出.它支持用户自定义函数和动态正则表达式等先进功能,是li ...
- linux四剑客-grep/find/sed/awk/详解-技术流ken
四剑客简介 相信接触过linux的大家应该都学过或者听过四剑客,即sed,grep,find,awk,有人对其望而生畏,有人对其爱不释手.参数太多,变化形式太多,使用超级灵活,让一部分人难以适从继而望 ...
随机推荐
- VS.NET(C#)--2.6_ASP.NET服务器控件层次结构
ASP.NET服务器控件层次结构 语法 <asp:ControlType Id="ControlID" Rubat="Server" Property=& ...
- win7用驱动精灵安装了bcm94352ac蓝牙驱动后还是不能用蓝牙的解决方法
驱动精灵安装了驱动后,设备管理器处显示Bluetooth USB,但是没法用蓝牙,找不到蓝牙图标,后来在华硕官方下载了win7的Broadcom 蓝牙驱动程序装上之后就好了
- J.U.C之Condition
此篇博客所有源码均来自JDK 1.8 在没有Lock之前,我们使用synchronized来控制同步,配合Object的wait().notify()系列方法可以实现等待/通知模式.在Java SE5 ...
- spring cloud工具的概念
spring cloud是一个基于spring boot实现的微服务架构开发工具.它为微服务架构中涉及的配置管理.服务治理.断路器.智能路由.微代理.控制总线.全局锁.决策竞选.分布式会话和集群状态管 ...
- JqueryAjax 常用复制
$.ajax({ type : "POST", url : "", data : {}, success : function(data) { } }); $. ...
- Nginx的反向代理和负载均衡服务
Nginx (engine x) 是一个高性能的HTTP和反向代理服务,也是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行. ...
- Linux之python3编译安装
一,前言 centos7默认是装有python的,咱们先看一下 [root@glh ~ 20:18:03]#python Python 2.7.5 (default, Jul 13 2018, 13: ...
- Docker本地镜像上传到阿里云仓库
登录阿里云 在容器镜像服务中先创建命名空间 随后创建镜像仓库 我使用的代码源是本地仓库 创建后点击仓库的管理 就可以看到阿里云提供的操作指南 (下面的操作每个人都不同,详情查看阿里云的操作指南) 输入 ...
- nginx的应用【虚拟主机】
Nginx主要应用: 静态web服务器 负载均衡 静态代理虚拟主机 虚拟主机 :虚拟主机,就是把一台物理服务器划分成多个“虚拟”的服务器,这样我们的一台物理服务器就可以当做多个服务器来使用,从而可以配 ...
- CentOS6和7启动流程
CentOS6启动流程 https://linux.cn/article-8807-1.html BIOS 开机自检,硬件自检 MBR MBR磁盘分区是一种使用最为广泛的分区结构,它也被称为DOS分区 ...