出处: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 详解的更多相关文章

  1. 【linux】linux命令grep + awk 详解

    linux命令grep  +  awk 详解 grep:https://www.cnblogs.com/flyor/p/6411140.html awk:https://www.cnblogs.com ...

  2. awk详解 数组

    第1章 awk命令基础 1.1 awk命令执行过程 1.如果BEGIN 区块存在,awk执行它指定的动作. 2.awk从输入文件中读取一行,称为一条输入记录.如果输入文件省略,将从标准输入读取 3.a ...

  3. Linux下Awk详解(转载)

    什么是Awk Awk是一种小巧的编程语言及命令行工具.(其名称得自于它的创始人Alfred Aho.Peter Weinberger 和 Brian Kernighan姓氏的首个字母).它非常适合服务 ...

  4. awk详解

    一.简介 强大的文本分析工具,基于指定规则浏览和抽取信息.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理.awk有3个不同版本: awk.nawk和ga ...

  5. linux脚本Shell之awk详解(二)

    三.printf的使用   print format 生成报表 %d        十进制有符号整数 %u        十进制无符号整数 %f        浮点数 %s        字符串 %c ...

  6. linux脚本Shell之awk详解

    一.基本介绍1.awk: awk是一个强大的文本分析工具,在对文本文件的处理以及生成报表,awk是无可替代的.awk认为文本文件都是结构化的,它将每一个输入行定义为一个记录,行中的每个字符串定义为一个 ...

  7. 5_find grep sed awk 详解

    find :查找文件系统中指定的文件.可以按文件名(-name)  权限(-perm) 归属人 查找. find   要查找文件的路径   表达式 *通配符  可以添加在文件名的任意位置 常用的例子( ...

  8. awk 详解+实例

    1. awk简介 awk是一种编程语言,用于在linux/unix下对文本和数据进行处理.数据可以来自标准输入.一个或多个文件,或其它命令的输出.它支持用户自定义函数和动态正则表达式等先进功能,是li ...

  9. linux四剑客-grep/find/sed/awk/详解-技术流ken

    四剑客简介 相信接触过linux的大家应该都学过或者听过四剑客,即sed,grep,find,awk,有人对其望而生畏,有人对其爱不释手.参数太多,变化形式太多,使用超级灵活,让一部分人难以适从继而望 ...

随机推荐

  1. VS.NET(C#)--2.6_ASP.NET服务器控件层次结构

    ASP.NET服务器控件层次结构 语法 <asp:ControlType Id="ControlID" Rubat="Server" Property=& ...

  2. win7用驱动精灵安装了bcm94352ac蓝牙驱动后还是不能用蓝牙的解决方法

    驱动精灵安装了驱动后,设备管理器处显示Bluetooth USB,但是没法用蓝牙,找不到蓝牙图标,后来在华硕官方下载了win7的Broadcom 蓝牙驱动程序装上之后就好了

  3. J.U.C之Condition

    此篇博客所有源码均来自JDK 1.8 在没有Lock之前,我们使用synchronized来控制同步,配合Object的wait().notify()系列方法可以实现等待/通知模式.在Java SE5 ...

  4. spring cloud工具的概念

    spring cloud是一个基于spring boot实现的微服务架构开发工具.它为微服务架构中涉及的配置管理.服务治理.断路器.智能路由.微代理.控制总线.全局锁.决策竞选.分布式会话和集群状态管 ...

  5. JqueryAjax 常用复制

    $.ajax({ type : "POST", url : "", data : {}, success : function(data) { } }); $. ...

  6. Nginx的反向代理和负载均衡服务

    Nginx (engine x) 是一个高性能的HTTP和反向代理服务,也是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行. ...

  7. Linux之python3编译安装

    一,前言 centos7默认是装有python的,咱们先看一下 [root@glh ~ 20:18:03]#python Python 2.7.5 (default, Jul 13 2018, 13: ...

  8. Docker本地镜像上传到阿里云仓库

    登录阿里云 在容器镜像服务中先创建命名空间 随后创建镜像仓库 我使用的代码源是本地仓库 创建后点击仓库的管理 就可以看到阿里云提供的操作指南 (下面的操作每个人都不同,详情查看阿里云的操作指南) 输入 ...

  9. nginx的应用【虚拟主机】

    Nginx主要应用: 静态web服务器 负载均衡 静态代理虚拟主机 虚拟主机 :虚拟主机,就是把一台物理服务器划分成多个“虚拟”的服务器,这样我们的一台物理服务器就可以当做多个服务器来使用,从而可以配 ...

  10. CentOS6和7启动流程

    CentOS6启动流程 https://linux.cn/article-8807-1.html BIOS 开机自检,硬件自检 MBR MBR磁盘分区是一种使用最为广泛的分区结构,它也被称为DOS分区 ...