zoukankan      html  css  js  c++  java
  • 文本处理三剑客之awk(报告生成器)

    文本处理三剑客之awk(报告生成器)

    awk是一款强大的报告生成器,不同于sed和grep,它的侧重点是如何把文本信息更好的展示出来,常用与统计和格式化输出。awk相当于微型的shell,有着自己一套语法结构,例如:循环结构,数组,条件判断,函数,内置变量等功能。

    awk在我认为简直就是文本处理时打劫放火一大利器。
    
    例如取出/etc/passwd中的第一列。
    
    [root@CentOS6 ~]# awk -F: '{print $1}' /etc/passwd
    root
    bin
    daemon
    adm
    ...
    常用选项
    选项参数说明
    -F 指明输入时用到的字段分隔符 如果不指定默认代表用正则表达式匹配多个空白字符
    -v var=value: 自定义变量  
    变量介绍说明
    FS 输入字段分隔符,默认为空白 同-F效果一样
    OFS 输出字段分隔符,默认为空白字符 ‘{print $1,OFS,$2}’
    RS 输入记录分隔符,指定输入时的换行符,原换行符仍有效  
    ORS 输出记录分隔符,输出时用指定符号代替换行符  
    NF 字段数量  
    NR 行号  
    FNR 各文件分别计数,行号 awk '{print FNR}' /etc/fstab /etc/inittab
    FILENAME 当前文件名  
    ARGC 命令行参数个数  
    ARGV 数组,保存的是命令行所给定的各参数  

     

    格式化输出参数介绍
    %c 显示字符的ASCII码
    %d, %i: 显示十进制整数
    %e, %E 显示科学计数法数值
    %f 显示为浮点数
    %g, %G 以科学计数法或浮点形式显示数值
    %s 显示字符串
    %u 无符号整数
    %% 显示% 自身
    #[.#] 第一个数字控制显示的宽度;第二个# 表示小数点后精度,%3.1f
    基本结构

    awk [options] 'BEGIN{ action;… } pattern{ action;… } END{ action;… }' file ...

    awk 程序通常由:BEGIN语句块(最初执行)、被模式匹配的语句块(中间执行)、END语句块三部分构成(最后执行)。program通常被单引号或双引号引中。不一定每种模式一定要用,pattern会最常用到 。

    基本格式
    print标准输出 printf 格式化输出

    print

       需要显示的内容逗号分割,支持字符串、数值、当前记录的字段、变量或者awk的表达式。

     

        
         awk -F: '{print $1,$3}' /etc/passwd($0代表整行)
        
         awk -F: '{print length($1),$1}' /etc/passwd  打印$1的字符数量 以及显示$1
    awk -F: 'i=1;j=1{print i,j}' /etc/passwd 请注意这里有个坑,写之前想下会是什么结果,看打印出来和自己想的是不是一样

    printf

      不会自动换行 需要制定换行控制符  “\n”
      需要指定格式,使看起来更简洁

    [root@station38 testscr]# awk -F: '{printf "%-20s%s\t%s\n",$1,$2,$3}' /etc/passwd

    root x 0

    bin x 1

    bin x 1

    bin x 1

    .....

    逻辑操作符和算术运算符
    算术运算支持赋值、算术运算、算术比较、模式匹配,支持正则。
    逻辑操作符理论上最好只有一个&&或者|| 这样可视性强
         
        awk –F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd
       awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd
    BEGIN/END 模式
    awk -F: 'BEGIN{print "AAAAAAAA"}{printf "%-15s%-20d\n",$1,$3}END{print "BBBBBBBB"}' /etc/passwd
     
    AAAAAAAA
    root           0                   
    bin            1                   
    bin            1                   
    bin            1  
    ...
    BBBBBBBB
    
    先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。
    性能比较time
    测试计算100以内3的倍数相加得数 显示耗时
    
    [root@station38 testscr]# time (seq -s + 3 3 100|bc) 1683 real 0m0.015s user 0m0.008s sys 0m0.006s
    条件表达式(三目表达式)
    selector?if-true-expression:if-false-expression
    
    如果之前的条件为真执行之前的条件,如果之前的条件为假则执行最后的条件.
    最后一个字段($NF)不等于 /sbin/nologin 为真,执行name="sysuser" ,在执行最后的条件。
    
    awk -F: '$NF != "/sbin/nologin"?name="sysuser":name="user"{printf "%-20s:%s\n",$1,$3}' /etc/passwd
    连接当前主机次数前三的IP
    netstat -nt | awk '/^tcp/{print $(NF-1)}' | awk -F: '{print $1}' | sort | uniq -c | sort -nr | head -n3
    
    访问太过频繁有危险扔黑名单 例如是 192.168.22.129的IP
    iptables -A INPUT -s 192.168.22.129 -p tcp --dport  80 -j REJECT
    条件语句和shell脚本编程里类型一样的,只不过这个不换行,而且使用括号的方式更类似C语言。接下来举两个例子
    查看用户属于是普通用户还是系统用户。
    [root@station38 testscr]# awk -F: '{print $3,$4}' /etc/passwd | awk '{i=1;while(i<=NF){if($i<500)print $i,"smaller";else print $i,"bigger";i++}}'
    0 smaller
    0 smaller
    993 bigger
    113 smaller
    113 smaller
    995 bigger
    992 bigger
    ......
    
    打印UUID 开头的行的每段有多少字符
    
    [root@station38 testscr]# awk '/^UUID/{i=1;while(i<=NF){print length($i);i++}}' /etc/fstab
    41
    1
    4
    8
    1
    1
    41
    ......
    
    找到/etc/grub2.cfg中开头可以有空白字符的行 后面跟linux16的行 显示并且显示有多少字符
    
    [root@station38 testscr]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){if(length($i)>=10)print $i,length($i);i++}}' /etc/grub2.cfg
    /vmlinuz-3.10.0-327.el7.x86_64 30
    root=UUID=2a9b6b86-35c8-415b-852a-78c30911a93c 46
    crashkernel=auto 16
    ......
    
    do-while的用法 while是条件为真执行循环,do是不管真假先执行一次。这是唯一的区别
    
    [root@station38 testscr]# awk '/^[[:space:]]*linux16/{i=1;do{print $i,length($i);i++}while(i<=NF)}' /etc/grub2.cfg
    linux16 7
    /vmlinuz-3.10.0-327.el7.x86_64 30
    root=UUID=2a9b6b86-35c8-415b-852a-78c30911a93c 46
    ro 2
    crashkernel=auto 16
    rhgb 4
    quiet 5
    LANG=en_US.UTF-8 16
    ......
    
    使用awk while循环实现1到100的加法
    [root@station38 testscr]# awk 'BEGIN{i=1;sum=0;while(i<=100){sum+=i;i++};print sum}'
    5050
  • 相关阅读:
    Java代理模式精讲之静态代理,动态代理,CGLib代理
    Java文件编译与反编译:javac命令和javap命令
    CAS机制总结
    try-catch-finally 与返回值的修改
    不同分布式锁的实现
    缓存算法(页面置换算法)-FIFO、LFU、LRU
    多线程的线程开销
    谈谈如何来查看GC日志
    JVM中常见的垃圾收集器
    前端大牛 博客集
  • 原文地址:https://www.cnblogs.com/MYue/p/6885469.html
Copyright © 2011-2022 走看看