(转)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,有人对其望而生畏,有人对其爱不释手.参数太多,变化形式太多,使用超级灵活,让一部分人难以适从继而望 ...
随机推荐
- Python初识对象
一 楔子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战>的游戏,你就思考呀,人狗作战,那至少需要2个角色,一个是人, 一个是狗,且人和狗都有不同的技能,比如人拿棍打狗, ...
- JTAG各类接口针脚定义、含义以及SWD接线方式
JTAG有10pin的.14pin的和20pin的,尽管引脚数和引脚的排列顺序不同,但是其中有一些引脚是一样的,各个引脚的定义如下. 一.引脚定义 Test Clock Input (TCK) --- ...
- JS权威指南读书笔记(三)
第七章 数组 1 数组的实现是经过优化的,用数字索引来访问数组元素一般来说比访问常规的对象属性要快的多. 2 数组直接量的语法允许有可选的结尾的逗号,故[ ; ; ]只有两个元素而非三个. 3 调用构 ...
- python简单页面爬虫入门 BeautifulSoup实现
本文可快速搭建爬虫环境,并实现简单页面解析 1.安装 python 下载地址:https://www.python.org/downloads/ 选择对应版本,常用版本有2.7.3.4 安装后,将安装 ...
- spark 机器学习 knn原理(一)
1.knnK最近邻(k-Nearest Neighbor,KNN)分类算法,在给定一个已经做好分类的数据集之后,k近邻可以学习其中的分类信息,并可以自动地给未来没有分类的数据分好类.我们可以把用户分 ...
- VMware网络配置三种网络模式(桥接、NAT、Host-only)
VMware网络配置三种网络模式(桥接.NAT.Host-only) 一.虚拟安装后三种网络模式显示 当安装好后,的“虚拟网络编辑器”中也存在三种模式,分别对应:桥接-VMnet0.Host-only ...
- C++——多维数组动态开辟与释放
前言 在讨论多维数组动态开辟与释放之前,先说说什么是二维数组静态开辟与释放. 形如这种就是静态开辟内存,事先画好了内存大小 #include<iostream> using namespa ...
- DDD总览
DDD总览 领域驱动设计(DDD)编码实践 目录 写在前面DDD总览实现业务的3种常见方式基于业务的分包领域模型的门面——应用服务业务的载体——聚合根实体 vs 值对象聚合根的家——资源库创生之柱 ...
- Resource接口
[转]https://blog.csdn.net/hbtj_1216/article/details/85487787 参考:官方文档 1 简介 Java标准库中的java.net.URL类和标准处理 ...
- mysql查询某一列的数据最大字节
语法:select 列名, length(列名) from 表名where length(列名) = ( select max(length(列名)) from 表名); 实例:select proj ...