zoukankan      html  css  js  c++  java
  • 文本处理三剑客之awk

    1.基本用法说明

    文本处理,输出格式化的文本报表,执行算数运算,执行字符串操作

    格式:

    awk [options] 'program' var=value file...

    awk [options] -f programfile var=value file...

    说明:

    program通常是被放在单引号中,并可以由三种部分组成

    ·BEGIN语句块   BEGIN{}:仅在开始处理文件中的文本之前执行一次

    ·模式匹配的通用语句块

    ·END语句块   END{}:仅在文本处理完成之后执行一次

    常见选项:

    -F“分隔符”指明输入时用到的字段分隔符,默认的分隔符是若干个连续空白符

    -v var=value 变量赋值

     第一步:执行BEGIN{action;...}语句块中的语句

    第二步:从文件或标准输入读取一行,然后执行pattern{action;...}语句块,他逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。

    第三步:当读至输入流末尾时,执行END{action;...}语句块

    BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化,打印输出表格的表头等语句通常可以写在BEGIN语句块中

    END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块

    pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{print},即打印每一个读取到的行,awk读取的每一行都会执行该语句块

     分隔符,域和记录

    由分隔符分隔的字段标记$1,$2....$n称为域标识,$0为所有域;注意和shell中的变量$符含义不同

    文件的每一行称为记录record

    如果省略action,则默认执行print$0的操作

    2.动作print

    格式

    print item1,item2,...

    说明

    逗号分隔符

    输出item可以是字符串,也可以是数值;当前记录的字段,变量或awk的表达式

    如省略item,相当于print$0

    固定字符需要用“”引起来,而变量和数字不需要

    范例

    [10:09:12 root@centos7 ~]$awk '{print "hello"}'
    [10:09:55 root@centos7 ~]$seq 3|awk '{print "hello"}' hello hello hello

      [10:11:35 root@centos7 ~]$seq 3|awk '{print 2*3}'
      6
      6
      6

    
    

    [10:18:37 root@centos7 ~]$awk -F: '{print "yang"}' hi
    wang
    wang
    wang
    wang
    wang

    该文件一共有几行,就打印几个yang

    [10:18:39 root@centos7 ~]$awk -F: '{print}' kao
    sdad:sdasd:sdjks:sdasd:sdsd
    sdsda:sdkaksd:sdkask
    ssadsd
    sdsd
    asdasdad

    打印全部内容

    [10:20:50 root@centos7 ~]$awk -F: '{print $0}' kao
    sdad:sdasd:sdjks:sdasd:sdsd
    sdsda:sdkaksd:sdkask
    ssadsd
    sdsd
    asdasdad

    加上$0也是打印全部的意思

    [10:22:45 root@centos7 ~]$awk -F: '{print $1,$3}' kao
    sdad sdjks
    sdsda sdkask
    ssadsd
    sdsd
    asdasdad

    以冒号为分隔符打印第一行和第三行

    [10:23:52 root@centos7 ~]$awk -F: '{print $1" "$3}' kao
    sdad sdjks
    sdsda sdkask
    ssadsd
    sdsd
    asdasdad

    中将用tab隔开

    [10:27:34 root@centos7 ~]$grep '^UUID' /etc/fstab |awk '{print $2,$3}'
    /boot xfs

    默认以空格做分隔符,不限制空格个数

    [10:44:22 root@centos7 ~]$df | awk -F"[ %]+" '{print $5}'
    Use
    0
    0
    2
    0
    4
    15
    1
    0

    以空隔百分号为分隔符取出分区利用率

    [10:50:28 root@centos7 ~]$df | awk -F' +|%' '/^/dev/sd/{print $1,$5}'
    /dev/sda1 15

    以空隔百分号为分隔符,以/dev/sd开头,取第一列和第五列

    [10:58:18 root@centos7 ~]$ifconfig eth0 |awk 'NR==2{print $2}'
    10.0.0.7

    以空格为分割符取第二行的第二列

    [11:15:16 root@centos7 ~]$ifconfig eth0 |awk '/netmask/{print $2}'
    10.0.0.7

    第二种方法

    [11:23:22 root@centos7 ~]$cat host 
    1 www.ybw.com
    2 blog.yang.com
    3 study.yang.com

    [11:24:23 root@centos7 ~]$awk -F"[ .]" '{print $2}' host 

    取出.ybw.com前面的主机名部分

    3.awk变量

    awk中的变量分为:内置和自定义变量

    常见内置变量

    范例

    FS:输入字段分隔符,默认为空白字符
    [11:33:37 root@centos7 ~]$awk -v FS=":" '{print $1,FS,$3}' /etc/passwd root : 0 bin : 1 daemon : 2 adm : 3 分隔符为:,引用FS

    [11:39:22 root@centos7 ~]$s=:;awk -F$s '{print $1$3}' /etc/passwd
    root0
    bin1

    设变量s=:,在awk里做为分隔符

    OFS:输出字段分隔符,默认为空白字符

    [11:39:30 root@centos7 ~]$awk -v FS=":" -v OFS="*" '{print $1,$3}' /etc/passwd
    root*0
    bin*1
    daemon*2

    OFS:输出字段分隔符,默认为空白字符

    NF:字段数量

    [11:48:28 root@centos7 ~]$awk -F: '{print NF}' /etc/passwd
    7
    7
    7

    显示这一行以冒号分割一共几个字段

    [11:51:53 root@centos7 ~]$awk -F: '{print $(NF-1)}' /etc/passwd
    /root
    /bin
    /sbin

    显示倒数第二个字段

    [14:17:02 root@aiyoubucuo ~]#cat nihao |awk -F"[ :]+" '{print $(NF-2)}'|tail -n +2|sort|uniq -c|sort -nr
    12 123.150.181.245
    1 114.246.101.61
    1 100.100.30.25

    取出连接数最多的三个ip

    NR:记录编号

    [14:19:08 root@aiyoubucuo ~]#cat nihao |awk -F"[ :]+" 'NR!=1{print $(NF-2)}'|sort|uniq -c|sort -nr
    12 123.150.181.245
    1 114.246.101.61
    1 100.100.30.25

    同上,NR!==1的意思是除去第一行都取,用来去表头

    [14:22:06 root@aiyoubucuo ~]#awk '{print NR,$0}' /etc/passwd
    1 root:x:0:0:root:/root:/bin/bash
    2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

    显示行号

    FNR:各文件分别计数,记录的编号

    [14:27:56 root@centos7 ~]$awk '{print FNR,$0}' /etc/issue /etc/redhat-release
    1 S
    2 Kernel on an m
    3
    1 CentOS Linux release 7.9.2009 (Core)
    [14:28:57 root@centos7 ~]$awk '{print NR,$0}' /etc/issue /etc/redhat-release
    1 S
    2 Kernel on an m
    3
    4 CentOS Linux release 7.9.2009 (Core)

    FILENAME:当前文件名

    [14:37:06 root@centos7 ~]$awk '{print FNR,FILENAME,$0}' /etc/issue /etc/redhat-release
    1 /etc/issue S
    2 /etc/issue Kernel on an m
    3 /etc/issue
    1 /etc/redhat-release CentOS Linux release 7.9.2009 (Core)

    4.自定义变量

    自定义变量是区分字符大小写的,使用下面方式将进行赋值

    -v var=value

    [14:37:32 root@centos7 ~]$awk -v test1=test2="hello,gawk" 'BEGIN{print test1,test2}'
    test2=hello,gawk 

    5.操作符

    [14:54:26 root@centos7 ~]$awk 'BEGIN{i=0;print i++,i}'
    0 1
    [14:54:36 root@centos7 ~]$awk 'BEGIN{i=0;print ++i,i}'
    1 1
    n++用法

    [14:57:46 root@centos7 ~]$seq 3|awk 'n++'
    2
    3

    n=1时++=2,所以不显示第一行。用来排除行首

    [15:01:52 root@centos7 ~]$awk -F: '$3>=1000' /etc/passwd
    ybw:x:1000:1000:ybw:/home/ybw:/bin/bash
    yang:x:1001:1001::/home/yang:/bin/bash

    操作符比较
    [15:02:23 root@centos7 ~]$seq 10 |awk 'NR%2==0'
    2
    4
    6
    8
    10
    [15:03:34 root@centos7 ~]$seq 10 |awk 'NR%2==1'
    1
    3
    5
    7
    9

    取奇数,偶数行

    逻辑操作符

    与:&&,并且关系

    或:||,或者关系

    非:!,取反

    [15:15:24 root@centos7 ~]$awk -F: '$3>=0 && $3<=1000 {print $1,$3}' /etc/passwd

    第三列数字大于等于0,并且小于等于1000

    [15:21:48 root@centos7 ~]$awk -F: '$3>=0 || $3<=1000 {print $1,$3}' /etc/passwd

    从0到大于1000

    [15:21:48 root@centos7 ~]$awk -F: '($3==0) {print $1,$3}' /etc/passwd

    只取等于第三列等于0的行

    [15:25:50 root@centos7 ~]$awk -F: '!($3==0) {print $1,$3}' /etc/passwd

    取反

    5.条件判断if-else

    [15:49:39 root@centos7 ~]$df | awk -F' +|%' '/^/dev/sd/{if($5>=10)print $1,$5}'
    /dev/sda1 15
    判断以/dev/sd开头行的第5列是否大约10,如果大于则输出$1,$5

    6.循环for

    [16:13:31 root@centos7 ~]$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){sum+=i};print sum}'
    5050

    7数组

    [16:54:36 root@centos7 ~]$ss -nta |awk 'NR!=1{state[$1]++}END{for (i in state){print i,state[i]}}'
    LISTEN 5
    ESTAB 1
    第一列不同的为i,state【i】为这种状态出现的次数
  • 相关阅读:
    【洛谷6620】[省选联考 2020 A 卷] 组合数问题(下降幂)
    【AtCoder】AtCoder Grand Contest 033 解题报告
    【AtCoder】AtCoder Grand Contest 034 解题报告
    【洛谷5445】[APIO2019] 路灯(树套树)
    【LOJ6059】「2017 山东一轮集训 Day1」Sum(倍增优化数位DP+NTT)
    【LOJ6159】「美团 CodeM 初赛 Round A」最长树链(树的直径)
    重新入门的Polya定理
    【洛谷6105】[Ynoi2010] y-fast trie(set)
    【BZOJ4480】 [JSOI2013] 快乐的jyy(回文自动机裸题)
    【LOJ6172】Samjia 和大树(树形DP+猜结论)
  • 原文地址:https://www.cnblogs.com/aiyoubucuo/p/14243115.html
Copyright © 2011-2022 走看看