zoukankan      html  css  js  c++  java
  • 随堂练习 文本处理三剑客 AWK(一)

    文本处理三剑客之 awk

    awk 工作原理和基本用法说明

    awk:Aho, Weinberger, Kernighan,报告生成器,格式化文本输出,GNU/Linux发布的AWK目前由自由软件基金会(FSF)进行开发和维护,通常也称它为 GNU AWK

    有多种版本:

      AWK:原先来源于 AT & T 实验室的的AWK

      NAWK:New awk,AT & T 实验室的AWK的升级版

      GAWK:即GNU AWK。所有的GNU/Linux发布版都自带GAWK,它与AWK和NAWK完全兼容

    gawk:模式扫描和处理语言,可以实现下面功能

      文本处理

      输出格式化的文本报表

      执行算数运算

      执行字符串操作

    格式:

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

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

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

    BEGIN语句块

    模式匹配的通用语句块

    END语句块

    常见选项:

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

      -v var=value 变量赋值

    Program格式:

    pattern{action statements;..}

    pattern:决定动作语句何时触发及触发事件,比如:BEGIN,END,正则表达式等

    action statements:对数据进行处理,放在{}内指明,常见:print, printf

    awk 工作过程

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

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

    第三步:当读至输入流末尾时,执行END{action;…}语句块BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块 pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块

    分割符、域和记录

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

      文件的每一行称为记录record

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

    常用的action分类

    output statements:print,printf

    Expressions:算术,比较表达式等

    Compound statements:组合语句

    Control statements:if, while等

    input statements

    awk控制语句

    { statements;… } 组合语句

    if(condition) {statements;…}

    if(condition) {statements;…} else {statements;…}

    while(conditon) {statments;…}

    do {statements;…} while(condition)

    for(expr1;expr2;expr3) {statements;…}

    break

    continue

    exit

    动作 print

    格式

    print item1, item2, ...

    说明:

    逗号分隔符

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

    如省略item,相当于print $0

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

    范例

    [root@centos8 ~]# awk  '{print "hello,awk"}'

    [root@centos8 ~]# seq 10 | awk '{print "hello,awk"}'
    hello,awk
    hello,awk
    hello,awk
    hello,awk
    hello,awk
    hello,awk
    hello,awk
    hello,awk
    hello,awk
    hello,awk

    [root@centos8 ~]# seq 3 | awk '{print 2*3}'
    6
    6
    6

    [root@centos8 ~]# awk -F: '{print "long"}' /etc/passwd

    [root@centos8 ~]# awk -F: '{print}' /etc/passwd

    [root@centos8 ~]# awk -F: '{print $0}' /etc/passwd

    [root@centos8 ~]# awk -F: '{print $1,$3}' /etc/passwd

    [root@centos8 ~]# awk -F: '{print $1" "$3}' /etc/passwd

    [root@centos8 ~]# grep "^UUID" /etc/fstab | awk {'print $2,$3'}

    / xfs
    /boot ext4
    /data xfs
    swap swap

    面题:取出网站访问量最大的前3个IP

    [root@centos8 ~]# awk '{print $1}' nginx.access.log | sort | uniq -c | sort -nr | head -n3

    213  122.54.68.23

    168  117.145.214.13

     56   223.158.167.123

    [root@centos8 ~]# awk '{print $1}' access_log | sort | uniq -c | sort -nr | head
    4870 172.20.116.228

    3429 172.20.116.208

    2834 172.20.0.222

    2613 172.20.112.14

    2267 172.20.0.227

    2262 172.20.116.179

    2259 172.20.65.65

    1565 172.20.0.76

    1482 172.20.0.200

    1110 172.20.28.145

    面试题:取出分区利用率

    [root@centos8 ~]# df | awk '{print $1,$5}'
    Filesystem Use%
    devtmpfs 0%
    tmpfs 0%
    tmpfs 2%
    tmpfs 0%
    /dev/sda2 3%
    /dev/sda3 1%
    /dev/sda1 15%
    tmpfs 0%

    #使用扩展的正则表达式
    [root@centos8 ~]# df | awk -F"[[:space:]]+|%"  '{print $5}'
    Use
    0
    0
    1
    0
    5
    1
    92
    1

    [root@centos8 ~]# df | awk -F'[[:space:]]+|%'  '{print $1,$5}'
    Filesystem Use
    devtmpfs 0
    tmpfs 0
    tmpfs 2
    tmpfs 0
    /dev/sda2 3
    /dev/sda3 1
    /dev/sda1 15
    tmpfs 0

    [root@centos8 ~]# df | grep "^/dev/sd" | awk -F"[[:space:]]+|%"  '{print $5}'

    3
    1
    15

    [root@centos8 ~]# df | grep '^/dev/sd' | awk -F'[[:space:]]+|%'  '{print $1,$5}'

    /dev/sda2 3
    /dev/sda3 1
    /dev/sda1 15

    [root@centos8 ~]# df | awk -F"[[:space:]]+|%"  '/^/dev/sd/{print $5}'

    3
    1
    15

    [root@centos8 ~]# df | awk -F'[[:space:]]+|%'  '/^/dev/sd/{print $1,$5}'

    /dev/sda2 3
    /dev/sda3 1
    /dev/sda1 15

    面试题:取 ifconfig 输出结果中的IP地址

    [root@centos8 ~]# ifconfig eth0 | awk '/netmask/{print $2}'

    10.0.0.100

    [root@centos6 ~]# ifconfig eth0 | awk -F " +|:" '/Mask/{print $4}'

    10.0.0.6

    [root@centos8 ~]# ifconfig eth0 | sed -nr '2s/^[0-9]+([0-9.]+) .*$/1/p'

    10.0.0.100

    [root@centos6 ~]# ifconfig eth0 | sed -nr '2s/^[0-9]+([0-9.]+) .*$/1/p'

    10.0.0.6

    面试题:文件host_list.log 如下格式,请提取”.longwang.com”前面的主机名部分并写入到回到该文件中

    [root@centos8 ~]# cat host_list.log
    1 www.longwang.com
    2 blog.longwang.com
    3 study.longwang.com
    4 linux.longwang.com
    5 python.longwang.com

    [root@centos8 ~]# awk -F"[ .]"  '{print $2}' host_list.log

    www
    blog
    study
    linux
    python

    [root@centos8 ~]# awk -F"[ .]" '{print $2}' host_list.log >> host_list.log

    [root@centos8 ~]#cat host_list.log
    1 www.longwang.com
    2 blog.longwang.com
    3 study.longwang.com
    4 linux.longwang.com
    5 python.longwang.com

    www
    blog
    study
    linux
    python

    awk变量

    常见的内置变量

    FS:输入字段分隔符,默认为空白字符,功能相当于 -F

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

    RS:输入记录record分隔符,指定输入时的换行符

    ORS:输出记录分隔符,输出时用指定符号代替换行符

    NF:字段数量

    NR:记录的编号

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

    FILENAME:当前文件名

    ARGC:命令行参数的个数

    ARGV:数组,保存的是命令行所给定的各参数,每一个参数:ARGV[0],......

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

    常见的内置变量

      FS:输入字段分隔符,默认为空白字符,功能相当于 -F
    范例:

    awk -v FS=':' '{print $1,FS,$3}' /etc/passwd

    awk -v FS=":" '{print $1FS$3}' /etc/passwd

    awk –F: '{print $1,$3,$7}' /etc/passwd

    S=:;awk -v FS=$S '{print $1FS$3}' /etc/passwd

    [root@centos8 ~]# awk -v FS=":" '{print $1FS$3}' /etc/passwd |head -n3
    root:0
    bin:1
    daemon:2

    [root@centos8 ~]# S=:;awk -F$S '{print $1,$3}' /etc/passwd|head -n3
    root 0
    bin 1
    daemon 2

    #-F 和 FS变量功能一样,同时使用会冲突
    [root@centos8 ~]# awk -v FS=":" -F";" '{print $1FS$3}' /etc/passwd |head -n3
    root:x:0:0:root:/root:/bin/bash;
    bin:x:1:1:bin:/bin:/sbin/nologin;
    daemon:x:2:2:daemon:/sbin:/sbin/nologin;

    [root@centos8 ~]# awk -F";" -v FS=":" '{print $1FS$3}' /etc/passwd |head -n3
    root:0
    bin:1
    daemon:2

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

    范例

    [root@centos8 ~]# awk -v FS=':'  '{print $1,$3,$7}' /etc/passwd | head -n1

    root 0 /bin/bash

    [root@centos8 ~]# awk -v FS=":"  -v  OFS=":"  '{print $1,$3,$7}'

    /etc/passwd|head -n1
    root:0:/bin/bash

      RS:输入记录record分隔符,指定输入时的换行符

    范例:

    awk -v RS=' ' ‘{print }’ /etc/passwd

      ORS:输出记录分隔符,输出时用指定符号代替换行符

    范例

    awk -v RS=' ' -v ORS='###' '{print $0}' /etc/passwd

      NF:字段数量

    范例

    #引用变量时,变量前不需加$

    [root@centos8 ~]# awk -F:  '{print NF}'  /etc/fstab

    [root@centos8 ~]# awk -F:  '{print $(NF-1)}'  /etc/fstab

    [root@centos8 ~]# ls /misc/cd/BaseOS/Packages/*.rpm | awk -F ":"  '{print $(NF-1)}' | sort | uniq -c

    389 i686
    208 noarch
    1060 x86_64

    面试题:接数最多的前3个IP

    [root@centos8 ~]# awk -F " +|:"  '{print $(NF-2)}'  sos.log | sort | uniq -c | sort -nr | head -n3

    20 223.66.64.148

    16 119.23.176.118

    13 182.250.65.202

    [root@centos8 ~]# awk -F " +|:"  '/^ESTAB/{print $(NF-2)}' sos.log | sort | uniq -c | sort -nr | head -n3

    15 223.77.34.147

    10 182.202.66.23

    8 116.134.156.88

    [root@centos8 ~]# ss -nt | grep "^ESTAB" | awk -F"[[:space:]]+|:"  '{print $(NF-2)}'

    10.0.0.1

    10.0.0.100

    10.0.0.1

    [root@centos8 ~]# ss -nt | awk -F"[[:space:]]+|:"  '/^ESTAB/{print $(NF-2)}'

    Address
    10.0.0.1

    [root@centos8 ~]# ss -tn | awk -F: '{print $(NF-1)}' | awk '/^[0-9]/{print $NF}' | sort | uniq -c | head -n3

    范例:每十分钟检查将连接数超过100个以上的IP放入黑名单拒绝访问

    [root@centos8 ~]# cat deny_dos.sh

    #!/bin/bash

    LINK=100

    while true ;do

      ss -nt | awk -F"[[:space:]]+|:"  '/^ESTAB/{print $(NF-2)}' | sort | uniq -c | while read count ip ;do

        if [ $count -gt $LINK ]; then

          iptables -A INPUT -s $ip -j REJECT

        fi

      done

    done

    [root@centos8 ~]# chmod +x /root/deny_dos.sh

    [root@centos8 ~]# crontab -e

    [root@centos8 ~]# crontab -l

    */10 * * * * /root/deny_dos.sh

    范例:

    [root@centos8 ~]# cat deny_dos.sh

    #!/bin/bash

    IPLIST=`awk -F" +|:"  '/^ESTAB/{print $(NF-2)}' sos.log | sort | uniq -c | sort -nr | head -n3 | awk '{print $2}'`

    for ip in $IPLIST;do

      iptables -A INPUT -s $ip -j REJECT

    done

      NR:记录的编号

    范例:

    [root@centos8 ~]# awk '{print NR,$0}' /etc/issue /etc/centos-release
    1 S
    2 Kernel on an m
    3
    4 CentOS Linux release 8.1.1911 (Core)

    范例:取ifconfig输出结果中的IP地址

    [root@centos8 ~]# ifconfig eth0 | awk '/netmask/{print $2}'
    10.0.0.100

    [root@centos8 ~]# ifconfig eth0 | awk 'NR==2{print $2}'
    10.0.0.100

    范例:

    [root@centos8 ~]# awk -F: '{print NR}' /etc/passwd
    1
    2
    3
    .......
    [root@centos8 ~]# awk -F: 'END{print NR}' /etc/passwd
    57

    [root@centos8 ~]# awk -F: 'BEGIN{print NR}' /etc/passwd
    0

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

    范例:

    awk '{print FNR}' /etc/fstab /etc/inittab

    [root@centos8 ~]# awk '{print NR,$0}' /etc/issue /etc/redhat-release
    1 S
    2 Kernel on an m
    3
    4 CentOS Linux release 8.0.1905 (Core)

    [root@centos8 script40]# awk '{print FNR,$0}' /etc/issue /etc/redhat-release
    1 S
    2 Kernel on an m
    3
    1 CentOS Linux release 8.0.1905 (Core)

      FILENAME:当前文件名

    范例:

    [root@centos8 ~]# awk '{print FILENAME}' /etc/fstab

    [root@centos8 ~]# 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 8.0.1905 (Core)

      ARGC:命令行参数的个数

    范例:

    [root@centos8 ~]# awk '{print ARGC}' /etc/issue /etc/redhat-release
    3
    3
    3
    3

    [root@centos8 ~]# awk 'BEGIN{print ARGC}' /etc/issue /etc/redhat-release
    3

      ARGV:数组,保存的是命令行所给定的各参数,每一个参数:ARGV[0],......

    范例:

    [root@centos8 ~]# awk 'BEGIN{print ARGV[0]}' /etc/issue /etc/redhat-release
    awk

    [root@centos8 ~]# awk 'BEGIN{print ARGV[1]}' /etc/issue /etc/redhat-release
    /etc/issue

    [root@centos8 ~]# awk 'BEGIN{print ARGV[2]}' /etc/issue /etc/redhat-release
    /etc/redhat-release

    [root@centos8 ~]# awk 'BEGIN{print ARGV[3]}' /etc/issue /etc/redhat-release

    自定义变量(区分字符大小写)
    -v var=value
    在program中直接定义

    范例:

    awk -v test='hello gawk' '{print test}' /etc/fstab

    awk -v test='hello gawk' 'BEGIN{print test}'

    awk 'BEGIN{test="hello,gawk";print test}'

    awk -F: '{sex="male";print $1,sex,age;age=18}' /etc/passwd

    cat awkscript

    {print script,$1,$2}

    awk -F: -f awkscript script="awk" /etc/passwd

  • 相关阅读:
    HDU 1124 Factorial
    hdu 1690 Bus System
    hdu 1113 Word Amalgamation
    POJ 2482 Stars in Your Window
    hdu 1385 ZOJ 1456 Minimum Transport Cost(经典floyd)
    hdu 1907 John
    VMware 虚拟机 安装 UBuntu 9.10 命令模式转换成窗口模试
    #pragma CODE_SEG __NEAR_SEG NON_BANKED详解
    Ubuntu 下Hadoop 伪分布式 hadoop0.20.2.tar.gz 的安装
    文件拷贝代码以及疑问
  • 原文地址:https://www.cnblogs.com/xuanlv-0413/p/13294174.html
Copyright © 2011-2022 走看看