• 随堂练习 文本处理三剑客 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

  • 相关阅读:
    sublime tex创建可服用的片段
    php unset
    使用VS.NET来制作安装程序
    手机暗码大全.(挺好玩的..)
    【转】双目运算符 "??"
    linuxcp命令
    ios——在iPhone程序中打开其它程序
    IOS地图项目01网络编程很难么???
    C# BitArray 实例
    Windows Phone 8使用初体验
  • 原文地址:https://www.cnblogs.com/xuanlv-0413/p/13294174.html
Copyright © 2020-2023  润新知