Day06 awk

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day06 awk相关的知识,希望对你有一定的参考价值。

一、awk基本用法

1.1 awk概述

awk是一个编程语言/数据处理引擎。基于模式匹配检查输入文本,逐行处理并输出。

1.1.1 记录

记录:awk把每一个以换行符结束的行称为一个记录。
记录分隔符:默认的输入和输出的分隔符都是回车,保存在内建变量ORS和RS中。

1.1.2 域

记录中每个单词称做“域”,默认情况下以空格或tab分隔。awk可跟踪域的个数,并在内建变量NF中保存该值。如$ awk ‘{print $1,$3}‘ test将打印test文件中第一和第三个以空格分开的列(域)。

1.1.3 pattern { action statements }

awk的基本模式是 pattern { action statements },action部分是可以省略的,缺省情况下是输出,即{print $0},至于pattern可以理解成是表达式,通过pattern表达式的值的真假,来确定是否要进行action。比如1,最简单的awk用来实现cat的功能就是 awk ‘1‘,这边1就是pattern,当然,1也可以是2,3,4,5等其他数字,但如果用字母的话,就不行,因为字母会解释成变量,变量初始值未定义,初始值为假,或者可以加个!反义

1.2 命令格式

awk [选项] ‘[条件]{编辑指令}‘ 文件
前置命令 | awk [选项] ‘[条件]{编辑指令1};{编辑指令2}‘
选项:F,v
条件:/正则/,数值/字符串比较,逻辑比较,运算符,BEGIN,END
编辑指令:print [变量],[常量]
变量:$n,$0,NF,NR 常量:必须以""括起来

1.3 选项

1.3.1 awk -F

指定分隔符,可省略(默认空格和tab位)
内建变量FS保存输入域分隔符的值,默认是空格或tab。可以同时使用多个域分隔符,这时应该把分隔符写成放到方括号中,如$awk -F‘[:\t]‘ ‘{print $1,$3}‘ test,表示以空格、冒号和tab作为分隔符。
输出域的分隔符默认是一个空格,保存在OFS中。如$ awk -F: ‘{print $1,$5}‘ test,$1和$5间的逗号就是OFS的值。

1.3.2 awk -v var=val

调用外部shell变量
a=1000
awk -v var=$a ‘BEGIN {print var}‘

1.4 内置变量

变量 用途
FS 保存或设置字段分隔符,例如FS=":"
$n 指定分割的第n个字段,如$1、$3分别表示第1、第3列
$0 当前读入的整行文本内容
NF 记录当前处理行的字段个数(列数)
NR 记录当前已读入行的数量(行数)
FNR 保存当前处理行在原文本内的序号(行号)
FILENAME 保存 awk 当前处理的(文件名)

1.5 条件

1.5.1 BEGIN{}

BEGIN模块后紧跟着动作块,这个动作块在awk处理任何输入文件之前执行。所以它可以在没有任何输入的情况下进行测试。它通常用来改变内建变量的值,如OFS,RS和FS等,以及打印标题。如:$ awk ‘BEGIN{FS=":"; OFS="\t"; ORS="\n\n"}{print $1,$2,$3}‘ test。上式表示,在处理输入文件以前,域分隔符(FS)被设为冒号,输出文件分隔符(OFS)被设置为制表符,输出记录分隔符(ORS)被设置为两个换行符。$ awk ‘BEGIN{print "TITLE TEST"}只打印标题。

1.5.2 END{}

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

1.5.3 {}

在读取文件中执行n次。默认就是这个条件
这三种条件可以单独使用,也可以组合使用

1.5.4 匹配操作符

用来在记录或者域内匹配正则表达式
~表示列匹配
!~表示对列匹配取反
awk -F: ‘$0 ~/^root/‘ /etc/passwd
root:x:0:0:root:/root:/bin/bash
#在一整行中以root开头
awk -F: ‘$0 ~/root/‘ /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
#在一整行中有root即可

1.5.5 数值和字符串比较

==等于 !=不等于

>= < <=

1.5.6 逻辑比较

&& ||
awk ‘$3>=9&&$3<=10‘ log#找出9:00-10:00的日志信息

1.5.7 运算符

      • / % 普通加减乘除
        ++ -- 自加自减,放在变量前后的意义有重要区别
        ++var 先给var赋值,再对var进行累加
        var++ 先使用var变量的值,再对var进行累加
        !a[$0]++
        这个要从awk的执行模式开始说,最后结合++运算符,和hash特色
        patten分析:
        1.使用了一个hash数组a
        2.这个数组a,又是使用$0这个变量作为下标,即文件的每行值
        3.当a[$0]未声明(udef)时,a[$0]为假。但是在未声明的情况下,进行一次a[$0]++后,a[$0]即为真
        4.! 取反的优先级高于++
        awk的基本模式是 ,pattern { action statements },action部分是可以省略的,缺省情况下是输出,即{print $0},至于pattern可以理解成是表达式,通过pattern表达式的值的真假,来确定是否要进行action
        结论:当相同的行第一次读入时,pattern为真,行输出,再次读入后,patten为假,行乎略。所以!a[$0]++可以去除一行中重复的记录,以记录作为数组(可以将a理解为数组)索引
        a[$1]++
        和上面的表达式同理,可以根据记录中某个域删除这个域相同的记录,也可以根据这个域相同,执行另外一些相应的操作
        += -= *= /=
        awk ‘BEGIN{x=3;y=4;print x+y}‘
        awk ‘BEGIN{x=2;print x+y}‘#就算y变量没定义,也可以直接用,默认值为0

        二、awk高级应用

        2.1 if指令

        必须放在{}里面才行

        2.1.1 if(条件){指令}

        if单分支指令

        2.1.2 if(条件){指令1}else{指令2}

        if双分支指令

        2.1.3 if(条件){指令1}else if (条件){指令2}

        if多分支指令
        统计普通用户有几个?系统用户有几个?
        awk -F: ‘{if($3 < 1000){x++}else{y++}}END{print "normal users:"x,"super users:"y}‘ /etc/passwd
        if($3 < 1000){x++}else{y++}
        END{print x,y}

        2.2 while指令

        while(条件){指令}

        2.3 for指令

        for(条件){指令}

        2.4 awk数组定义

        awk ‘BEGIN{a[xx]=11;a[yy]=22;print a[xx],a[yy]}‘
        awk支持数组直接调用数组元素,而不是用0,1,2数字来调用
        示例:
        统计httpd_access_log的访问人数
        准备工作:
        使用ab软件模拟100个人访问,每个人100000次点击,生成access_log
        ab -c 100 -n 10000 http://192.168.4.7/
        指令:
        awk ‘{ip[$1]++}END{for (i in ip){print i,ip[i]}}‘ /var/log/httpd/access_log |awk ‘$2>500{print $1}‘
        指令分解分析:
        ip[$1]是一个数组变量,下标为$1。$1也是变量,是读取的文件的第一列
        ip[$1]++
        第一次读到ip[4.2]++,由于ip[4.2]不存在,首先赋值为0,再自加1,因此得到的值ip[4.2]=1
        第二次读到ip[4.2],由于ip[4.2]已存在,使用原有值=1,再自加1,因此得到的值ip[4.2]=2
        以此类推
        for (i in ip){print i,ip[i]}是一个for循环,小括号里面是判断条件。i的值是ip这个数组的所有元素,即i in 4.2 4.5。
        打印出来的结果
        $1 $2
        4.2 2
        4.5 1
        管道后的awk是用来判断异常情况并输出,$2>500的项就打印$1出来

        2.5 例子

        2.5.1 显示网卡流量

        ifconfig eth0|awk ‘/RX p/{print $5}‘

        2.5.2获取eth0的ip地址

        ifconfig eth0 |awk -F ‘[ :]+‘ ‘NR==2 {print $4}‘

        2.5.3 显示100以内可以被7整除或者包含7的数字

        seq 100|awk ‘$1%7==0||$1~/7/‘

        2.5.4 统计/etc/passwd文件中出现多少次‘root‘

        awk -F [:/] ‘{i=1}{while(i<=NF){if($i~/root/){j++};i++} }END{print j}‘ /etc/passwd
        awk是逐行读入文本
        读入第一行的时候:
        初始i=1,$1==root,条件匹配j++=1 i++=1; $3=root,条件匹配j++=2 i++=2
        读入第二行的时候
        when i=2 so no $ equal root then j=2 after i=3
        when i=3 so $1 equal root then j=3 after i=4

以上是关于Day06 awk的主要内容,如果未能解决你的问题,请参考以下文章

DAY 19

Day08_固化命令grepsed及awk命令

day12

009day--grep和sed作业及awk作业

Day10-1正则工具简介 下

shell训练DAY24