简介

awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。

awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报 表,还有无数其他的功能

使用方法

awk'{pattern + action}' {filenames}

awk :对于文件中一行行的独处来执行操作

调用方法

1.命令行方式

awk [-F  field-separator]  'commands'  input-file(s)

其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。

在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。

2.shell脚本方式

将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。

相当于shell脚本首行的:#!/bin/sh

可以换成:#!/bin/awk

3.将所有的awk命令插入一个单独文件,然后调用:

awk -f awk-script-file input-file(s)

其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。

工作流程

awk的工作流程师这样的,读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域, $0则表示所有域,$1表示第一个域,$n表示第n个域。 默认域分隔符是"空白键" 或 "[tab]键",所以$1表示登录用户,$3表示登录用户ip,以此类推

1.基本用法

只显示最近登录的5个账号

[root@www ~]$ last -n  | awk'{print $1}'
root
root
root
dmtsai
root

只显示/etc/passwd的账户

[root@www ~]$ cat /etc/passwd |awk  -F ':''{print $1}'
root
daemon
bin
sys

如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以tab键分割

[root@www ~]$ cat /etc/passwd |awk  -F ':''{print $1"\t"$7}'
root /bin/bash
daemon /bin/sh
bin /bin/sh
sys /bin/sh

搜索/etc/passwd有root关键字的所有行

[root@www ~]$ cat /etc/passwd | awk -F':' '/root/'
root:x:::root:/root:/bin/bash
operator:x:::operator:/root:/sbin/nologin

找/etc/passwd 以root开头的

[yangjiao@www ~]$ cat /etc/passwd | awk -F':' '/^root/'
root:x:::root:/root:/bin/bash

2.内置变量

ARGC

命令行参数个数

NF

浏览记录的域个数

AGRV

命令行参数排列

NR

已读的记录数

ENVIRON

支持队列中系统环境变量的使用

OFS

输出域分隔符

FILENAME

awk浏览的文件名

ORS

输出记录分隔符

FNR

浏览文件的记录数

RS

控制记录分隔符

FS

设置输入域分隔符,同- F选项

NF

浏览记录的域个数

打印每一行的行数

[root@www ~]$ ls -l | awk '{print NR " " $1}'
total
drwx------
drwx------+
drwx------+
drwx------+
drwx------@
drwx------+
drwx------+
drwx------+
drwxr-xr-x+

再理解如下应该比较简单了

[root@www ~]$awk  -F ':'  '{printf("filename:%s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
filename:/etc/passwd,linenumber:,columns:,linecontent:root:x:::root:/root:/bin/bash
filename:/etc/passwd,linenumber:,columns:,linecontent:daemon:x:::daemon:/usr/sbin:/usr/sbin/nologin
filename:/etc/passwd,linenumber:,columns:,linecontent:bin:x:::bin:/bin:/usr/sbin/nologin
filename:/etc/passwd,linenumber:,columns:,linecontent:sys:x:::sys:/dev:/usr/sbin/nologin
filename:/etc/passwd,linenumber:,columns:,linecontent:sync:x:::sync:/bin:/bin/sync
filename:/etc/passwd,linenumber:,columns:,linecontent:games:x:::games:/usr/games:/usr/sbin/nologin

3.数组和计算

因为awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。

[root@www ~]$ awk -F ':''BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
0 root
daemon
bin
sys
4 sync5 games

准备测试文件

[root@www ~]$ cat test.txt

8888
[root@www ~]awk '{name[x++]=$1};END{for(i=0;i<NR;i++) print i, name[i]}' test.txt
0 5555
1 4444
2 2222
3 3333
4 7777
5 8888

求和

[root@www ~]$awk '{sum+=$1} END {print "sum=",sum}' test.txt
sum=

求平均值

[root@www ~]$ awk '{sum+=$1} END {print "avg=",sum/NR}' test.txt
avg= 5369.83

求最大值

[root@www ~]$ awk 'BEGIN {max=0} {if($1>max) max=$1 fi} END {print "MAX=",max}' test.txt
MAX= [root@www ~]$ awk 'BEGIN{max=0;print "max="max} {max=($1>max)?$1:max; print $1, "Now max is" max}' test.txt
max=
Now max is5555
Now max is5555
Now max is5555
Now max is5555
Now max is7777
Now max is8888

求最小值

[root@www ~]$ awk 'BEGIN{min=9999999}{if($1<min) min=$1} END {print "MIN=",min}' test.txt
MIN=

统计某个文件夹下的文件占用的字节数

[root@www ~]$ls -l | awk 'BEGIN{size=0;} {size=size+$5} END {print "size is", size}'
size is

4.条件操作符

<、<=、==、!=、>=、~匹配正则表达式、!~不匹配正则表达式

匹配:awk '{if ($4~/ASIMA/) print $0}' temp 表示如果第四个域包含ASIMA,就打印整条

精确匹配:awk '$3=="48" {print $0}' temp    只打印第3域等于"48"的记录

不匹配:  awk '$0 !~ /ASIMA/' temp      打印整条不包含ASIMA的记录

不等于:  awk '$1 != "asima"' temp

小于:    awk '{if ($1<$2) print $1 "is smaller"}' temp

设置大小写: awk '/[Gg]reen/' temp      打印整条包含Green,或者green的记录

任意字符: awk '$1 ~/^...a/' temp    打印第1域中第四个字符是a的记录,符号’^’代表行首,符合’.’代表任意字符

或关系匹配: awk '$0~/(abc)|(efg)/' temp   使用|时,语句需要括起来

AND与关系:  awk '{if ( $1=="a" && $2=="b" ) print $0}' temp

OR或关系:   awk '{if ($1=="a" || $1=="b") print $0}' temp

awk有三种循环: while循环;for循环;special for循环。

$ awk '{ i = 1; while ( i <= NF ) { print NF,$i; i++}}' test。变量的初始值为1,若i小于可等于NF(记录中域的个数),则执行打印语句,且i增加1。直到i的值大于NF.

$ awk '{for (i = 1; i<NF; i++) print NF,$i}' test。作用同上。

bread continue 语句。break用于在满足条件的情况下跳出循环;continue用于在满足条件的情况下忽略后面的语句,直接返回循环的顶端。如:

{for ( x=; x<=NF; x++)
if ($x<){print "Bottomed out!"; break}}
{for ( x=; x<=NF; x++)
if ($x==){print "Get next item"; continue}} next 语句从输入文件中读取一行,然后从头开始执行awk脚本。如: {if ($ ~/test/){next}
else {print}
} exit 语句用于结束awk程序,但不会略过END块。退出状态为0代表成功,非零值表示出错。
if 语句
格式:
{if (expression){
statement; statement; ...
}
}
$ awk '{if ($1 <$2) print $2 "too high"}' test。如果第一个域小于第二个域则打印。 $ awk '{if ($1 < $2) {count++; print "ok"}}' test.如果第一个域小于第二个域,则count加一,并打印ok。

if/else语句,用于双重判断

格式:
{if (expression){
statement; statement; ...
}
else{
statement; statement; ...
}
}

$ awk '{if ($1 > 100) print $1 "bad" ; else print "ok"}' test。如果$1大于100则打印$1 bad,否则打印ok。

$ awk '{if ($1 > 100){ count++; print $1} else {count--; print $2}' test。如果$1大于100,则count加一,并打印$1,否则count减一,并打印$1。

[root@www ~]$awk 'BEGIN {BASE="7000"} {if($1<BASE) print $0}' test.txt
[root@www ~]$ awk '{total+=$1};END{print total}' test.txt

5.BEGIN和END模块

BEGIN模块后紧跟着动作块,这个动作块在awk处理任何输入文件之前执行。所以它可以在没有任何输入的情况下进行测试。它通常用来改变内建变量的值,如OFS,RS和FS等,以及打印标题

END不匹配任何的输入文件,但是执行动作块中的所有动作,它在整个输入文件处理完成后被执行。如$ awk 'END{print "The number of records is" NR}' test,上式将打印所有被处理的记录数。

6.举个例子

有a.txt如下

"北京" =>
"上海" =>
"天津"=>
"重庆"=>
"河北省"=>
"山西省"=>
"内蒙古"=>
"辽宁省"=>
"吉林省"=>
"黑龙江省"=>

 现把key和value互换并去掉空格,用如下命令,或者先去掉空格,用下边第二条命令

cat a.txt | awk -F'=>'  '{printf("%s=>%s\n",$2,$1)}' | sed 's/\s\+//g' > b.txt

cat a.txt | sed 's/\s\+//g' | awk -F'=>' '{printf("%s => %s\n",$2,$1)}' > b.txt

 修改完后的b.txt如下

=>"北京"
=>"上海"
=>"天津"
=>"重庆"
=>"河北省"
=>"山西省"
=>"内蒙古"
=>"辽宁省"
=>"吉林省"
=>"黑龙江省"

  

7.常用例子

cat www.slow.log. | grep -E  "08-May-2019 [^]]+" -o | awk -F "\t" '{a[$1]++}END{for (i in a) print i,a[i]}'

cat www.slow.log  | grep -E "09-May-2019 [0-9]+:[0-9]+:[0-9]+" -o

cat forbidword.txt | awk '{a[$1]++}END{for (i in a) {if(a[i]>1)print i,a[i]}}'

cat access.log.minute. |grep mtoutiao/ads |  grep -E "ls=[^&]+" -o | awk '{a[$1]++}END{for(i in a) print i,a[i]}'

参考文档:https://www.cnblogs.com/losbyday/p/5854707.html

https://www.cnblogs.com/losbyday/p/5854725.html

https://www.cnblogs.com/bugingcode/p/8287914.html

https://www.cnblogs.com/emanlee/p/3327576.html


shell学习(4)- awk的更多相关文章

  1. Shell 学习—AWK介绍

    Shell 学习—AWK = = = 安装awk root@kiki-desktop:~/shell# apt-get install gawk gawk-doc = = = awk 是一种程序语言. ...

  2. Shell—学习之心得

    由于项目要招聘需要有经验shell开发人员(awk编程),而作为技术面试官(暂时)的我对shell编程不太熟:当然以前也写过一些shell脚本来满足项目的需求—备份环境,数据库(逻辑).假如只是针对a ...

  3. shell学习笔记

    shell学习笔记 .查看/etc/shells,看看有几个可用的Shell . 曾经用过的命令存在.bash_history中,但是~/.bash_history记录的是前一次登录前记录的所有指令, ...

  4. shell学习指南-阅读笔记

    shell学习指南真不是刚开始学习shell应该看得书,虽然其中讲了简单的linux命令,shell语法等,但是每章也有些深入和生僻地方,我想如果我刚学shell看到这样的地方一定会头疼的要死.或许也 ...

  5. Shell学习之结合正则表达式与通配符的使用(五)

    Shell学习之结合正则表达式与通配符的使用 目录 通配符 正则表达式与通配符 通配符 通配符的使用 正则表达式 正则表达式 正则表达式的使用 通配符 正则表达式与通配符 正则表达式用来在文件中匹配符 ...

  6. [转帖][Bash Shell] Shell学习笔记

    [Bash Shell] Shell学习笔记 http://www.cnblogs.com/maybe2030/p/5022595.html  阅读目录 编译型语言 解释型语言 5.1 作为可执行程序 ...

  7. shell学习笔记汇总

    1.shell脚本中函数使用 函数定义在前,调用在后,顺序反了就没有效果了.函数调用为:函数名 参数列表 函数内部通过以下变量访问函数的参数:shell脚本函数中: $0: 这个脚本的名字 $n: 这 ...

  8. shell学习总结之自定义函数

    shell学习总结之自定义函数 Myfun (){ echo -n "now i is $i " ! [ "$i" ] && exit ; ec ...

  9. SHELL学习笔记----IF条件判断,判断条件

    SHELL学习笔记----IF条件判断,判断条件 前言: 无论什么编程语言都离不开条件判断.SHELL也不例外.  if list then           do something here   ...

  10. shell 学习笔记1501-1800

    .巧用bash的{}扩展备份目录: cp file.txt{,.bak} .利用at执行一次性命令: echo "ls -l" | at midnight #Execute a c ...

随机推荐

  1. AndroidPageObjectTest_Chained.java

    以下代码使用ApiDemos-debug.apk进行测试 //这个脚本用于演示PageFactory的功能:链式注解@AndroidFindBys.@IOSFindBys.具体用法参考页面类的代码. ...

  2. 剑指Offer:旋转数组的最小数字【11】

    剑指Offer:旋转数组的最小数字[11] 题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4 ...

  3. target!

    工作到现在也有8个月了,从学生时代想从事嵌入是开发,到工作中从事android开发,跨度还是比较大的:曾经想从事这些消费类电子产品的开发,想从一个用户变成一个生产者,但是真正进入到这一行之后,才知道在 ...

  4. java中设计模式详解

    一.设计模式的分类 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代理模式.外 ...

  5. hadoop学习之旅1

    大数据介绍 大数据本质也是数据,但是又有了新的特征,包括数据来源广.数据格式多样化(结构化数据.非结构化数据.Excel文件.文本文件等).数据量大(最少也是TB级别的.甚至可能是PB级别).数据增长 ...

  6. 脚踏实地学C#4-静态类

    起因 问:静态类可以实现接口及继承? 答:都不可以 思考:为什么不可以呢? 学习 静态类,有时我们又称为工具类(密封抽象类),从MSDN文档没有直接静态类的定义,这里只能说用static(不能用于结构 ...

  7. MPEG学习

    Mpeg:moving picture experts group 移动图片专家组 导入:Mpeg技术在我理解就是我们对音视频信息的一个输出标准.主要包括MPEG-1.MPEG-2.MPEG-4.MP ...

  8. I.MX6 Surfaceflinger 机制

    /**************************************************************************** * I.MX6 Surfaceflinger ...

  9. javamail - 发件、收件(SSL连接)

    需要的包:mail.jar  jsse.jar(说明:jsse.jar是jre自带的,如果jdk1.5及以下需要Java Activation Framework框架的activation.jar) ...

  10. 7、html的body内标签之图片及表格

    一.image <a href="https://www.baidu.com" target="_blank"> <img src=" ...