• 【三剑客】awk命令2


    1. 程序结构: Begin 和 End模块

    awk的程序的结构:Begin块,Body块,End块。

    • BEGIN块:BEGIN {awk-commands}
      • BEGIN块在被程序启动时启动,且只执行一次。
      • 这是一个很好的初始化变量的地方,常常被用来修改内置变量RS,FS,OFS,ORS等的值。
      • BEGIN是awk的关键字,必须大写。
      • 可选的
    • BODY块:  /pattern/{awk-commands(action)}
      • 主体块适用于awk的每个输入行命令。
      • 默认情况下,awk执行每一行命令,但可以通过pattern限制。
      • body块没有关键字
    • END块: END {awk-commands}
      • END块在程序结束时执行,在awk读取完所有的文件的时候,再执行的。
      • 一般用来输出一个结果(累加,数组结果)
      • END是awk关键字,必须是大写。
      • 可选的。
    [root@oldboy test]# awk 'BEGIN {print "Sr No Name Sub Marks	"} {print} END{print "****END***"}' marks.txt 
    Sr No Name Sub Marks
    1) Amit Physics 80
    2) Rahul Maths 90
    3) Shyam Biology 87
    4) Kedar English 85
    5) Hari History 89
    ****END***

    案例:统计文件里面的空行数量

    # grep查看文件内的空行数量
    [root@oldboy test]# grep -c '^$' /etc/services 16

    # 遇到空行print 数量(增量+1) [root@oldboy test]# awk '/^$/{a=a+1;print a}END{print "Blank Record Count:",a}' /etc/services 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Blank Record Count: 16
    # 仅输出END块,空行数量
    [root
    @oldboy test]# awk '/^$/{a=a+1} END{print "Blank Record Count:",a}' /etc/services
    Blank Record Count: 16

    问题: awkfile2.txt 里面 以:为分隔符,区域3 大于15,一共有多少个?

     awk -F ":" '$3>15{a=a+1} END{print a}' awkfile2.txt

    示例:找出环境变量$PATH中,所有只有三个任意字符的命令,例如:tee,并将它们重定向到command.txt中,要求一行显示1个,并在文件尾部统计他们的个数。

    find `echo $PATH|tr ":" " "` -type f -name "???"|awk '{cnt+=1;print $0} END{print "Total Count:",cnt}' >>command.txt

    示例:1+2+...+100,加到100的值,用awk实现。

    • awk '{if (a<100) {++a;b+=a;print a,b}}' /etc/services
    • awk 'BEGIN {for (i=1;i<101;++i) {s+=i;print s}}'|tail -1
    • echo |awk 'BEGIN {for (i=1;i<101;++i) {s+=i}} END{print s}' 

    2. awk数组

    • 数组的索引不必是连续的设定的值;
    • 可以使用字符串或数字作为数组的索引
    • 不需要事先声明数组的大小
    • 数组可以在运行时扩展/收缩

    数组的语法:

        array_name[index] = value

    其中,array_name是数组的名称,index是数组索引,value是任意值分配给数组的元素。

    2.1 创建 array_name[index] = value

    [root@oldboy test]# awk 'BEGIN{fruits["mango"]="yellow";fruits["orange"]="orange";print fruits["orange"] "
    " fruits["mango"]}'  
    orange
    yellow

    2.2 删除 delete array_name[index]

    使用delete语句从数组中删除元素。

    [root@oldboy test]# awk 'BEGIN{fruits["mango"]="yellow";fruits["orange"]="orange";delete fruits["orange"];print fruits["mango"];print fruits["orange"]}'
    yellow
    
    [root@oldboy test]# 

    2.3 多维数组:用一维数组模拟多维数组

    awk只支持一维数组,但是我们可以很容易地模拟使用一维阵列本身的多维阵列。 

    例如下面是3×3的三维阵列:

    100 200 300
    400 500 600
    700 800 900

    另外,在上述示例array[0] [0]存储100,array[0][1]存储200等。要在位置array[0] [0]存储100,我们可以使用下面的语法:

    array["0,0"] = 100

    虽然我们已经给定0,0为索引,这些都不是两个索引。在现实中,它只是一个索引以字符串0,0。

    下面简单的例子模拟2-D数组:

    awk 'BEGIN {
    array["0,0"] = 100;
    array["0,1"] = 200;
    array["0,2"] = 300;
    array["1,0"] = 400;
    array["1,1"] = 500;
    array["1,2"] = 600;
    # print array elements
    print "array[0,0] = " array["0,0"];
    print "array[0,1] = " array["0,1"];
    print "array[0,2] = " array["0,2"];
    print "array[1,0] = " array["1,0"];
    print "array[1,1] = " array["1,1"];
    print "array[1,2] = " array["1,2"];
    }'
    在执行上面的代码后,得到以下结果:
    array[0,0] = 100
    array[0,1] = 200
    array[0,2] = 300
    array[1,0] = 400
    array[1,1] = 500
    array[1,2] = 600

    我们还可以在排序其元素/索引于阵列执行各种操作。

    为了达到这个目的,可以使用AWK的asort以及asorti函数。我们将看到在后面的章节这些函数的使用。

    2.4 无序和有序的关联数组

    awk中的数组都是关联数组,数字索引也会变成字符串索引:

    [root@oldboy test]# awk 'BEGIN {cities[1]="beijing"
    > cities[2]="shanghai"
    > cities["three"]="guangzhou"
    > for (c in cities) {print cities[c]}
    > print cities[1]
    > print cities["1"]
    > print cities["three"]
    > }'
    guangzhou
    beijing
    shanghai
    beijing
    beijing
    guangzhou

    for循环的输出,因为数组是关联数组,默认是无序的。通过for循环得到的是无序的数组。

    如果需要得到有序数组,需要通过下标指定获得。

    2.5 awk数组的典型应用

    案例:用awk查看服务器连接状态并汇总

    [root@oldboy test]# netstat -an
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address               Foreign Address             State      
    tcp        0      0 0.0.0.0:3306                0.0.0.0:*                   LISTEN      
    tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      
    tcp        0      0 192.168.0.109:22            192.168.0.102:53242         ESTABLISHED 
    tcp        0      0 :::80                       :::*                        LISTEN      
    tcp        0      0 :::22                       :::*                        LISTEN      
    udp        0      0 0.0.0.0:68                  0.0.0.0:*                               
    Active UNIX domain sockets (servers and established)
    Proto RefCnt Flags       Type       State         I-Node Path
    unix  2      [ ACC ]     STREAM     LISTENING     9885   /var/lib/mysql/mysql.sock
    unix  2      [ ACC ]     STREAM     LISTENING     7111   @/com/ubuntu/upstart
    unix  2      [ ]         DGRAM                    7512   @/org/kernel/udev/udevd
    unix  5      [ ]         DGRAM                    9369   /dev/log
    unix  2      [ ]         DGRAM                    209043 
    unix  2      [ ]         DGRAM                    20157  
    unix  2      [ ]         DGRAM                    9921   
    unix  3      [ ]         DGRAM                    7530   
    unix  3      [ ]         DGRAM                    7529   
    [root@oldboy test]# netstat -an|awk '/^tcp/{++s[$NF]} END{for (a in s) print a,s[a]}'
    ESTABLISHED 1
    LISTEN 4

    ++s[$NF] 即将s作为数组的名称,索引是$NF,通过++s增量加1的方式,遇到一次s["Listen"]的值加1,非常的高校实用。

    等价的表示方式为:

    [root@oldboy test]# netstat -an|awk '/^tcp/{state[$NF]+=1;print s state[$NF] $NF} END{for (a in state) print a,state[a]}'
    1LISTEN
    2LISTEN
    1ESTABLISHED
    3LISTEN
    4LISTEN
    ESTABLISHED 1
    LISTEN 4

    案例:统计web日志访问流量,要求输出访问次数,请求页面或图片,每个请求的总大小,总访问流量的大小汇总。

    需要结合httpd服务的日志文件进行解析。

    面试题:处理以下文件内容,将 域名计算计数 排序处理(去重)

    http://www.etiantian.org/index.html
    http://www.etiantian.org/1.html
    http://post.etiantian.org/index.html
    http://mp3.etiantian.org/index.html
    http://www.etiantian.org/3.html
    http://post.etiantian.org/2.html

    答案:

    [root@oldboy test]# awk -F "/" '{print $3}' html.txt |sort -rn|uniq -c
          3 www.etiantian.org
          2 post.etiantian.org
          1 mp3.etiantian.org
    [root
    @oldboy test]# awk -F "/" '{++domain[$3];print $3,domain[$3]}' html.txt www.etiantian.org 1 www.etiantian.org 2 post.etiantian.org 1 mp3.etiantian.org 1 www.etiantian.org 3 post.etiantian.org 2 [root@oldboy test]# awk -F "/" '{++domain[$3]} END{for (a in domain) print a,domain[a]}' html.txt mp3.etiantian.org 1 post.etiantian.org 2 www.etiantian.org 3

    3. if语句

    awk提供了类似C语言的if语句。

    if ( $1== "foo" ) {
      if ( $2== "foo" ) {
        print "uno"
      } else
        print "one"
    } elseif ($1== "bar" )
      print "two"
    } else
      print "three"
    }
    }

    使用if语句还可以将代码:

    ! /match pattern/ {print $1}

    转换成:

    { 
        if ($0 !~/match pattern/) {
            print $1
        }    
    }

    if语句,它只是测试条件,并执行特定操作,这取决于条件。

    if语句语法:

      if (conditon) action

      if (condition) {action1 action2 action3 ... action-n}

    if-else语句语法:

      if (conditon) action-1 else action-2

    if-else-if阶梯语法:

      if (condition1) action-1 else if (condition2) action2 else if (condtiton3) action3

    示例:检查给定的数是否为偶数。

    [root@oldboy test]# awk 'BEGIN{num=10;if (num%2==0) printf "%d is even number.
    ",num}'
    10 is even number.
    [root@oldboy test]# awk 'BEGIN{num=10;if (num%2==0) printf "%d is even number.
     else",num; else printf "%d is odd number.
    ",num}'
    10 is even number.
     root@oldboy test]# awk 'BEGIN{num=9;if (num%2==0) printf "%d is even number.
     else",num; else printf "%d is odd number.
    ",num}'  
    9 is odd number.
    # if-else-if 示例:
    [root@oldboy test]# awk 'BEGIN { > a=30; > if (a==10) > print "a=10"; > else if (a==20) > print "a=20"; > else if (a==30) > print "a=30"; > }' a=30

    4. 循环结构:for循环,while循环,do-while循环

    4.1 for循环

    for循环语法:

    for (initalisation; condition; increment/decrement) action

     示例:

    [root@oldboy test]# awk 'BEGIN{for (i=1;i<=5;++i) print i}'   # 初始化动作i=1;条件i<=5;增量或减量
    1
    2
    3
    4
    5

    4.2 while循环

    while循环语法:

    while (condition)
      action

     awk首先检查条件,如果条件为真,就执行操作,不断重复,只要循环条件满足为真。

    [root@oldboy test]# awk 'BEGIN {i=1; while (i<6) {print i; ++i}}'          
    1
    2
    3
    4
    5

    4.3 do-while循环

    do-while循环语法:

    do
      action
    while (condition)

    do-while循环类似于while循环,不同之处在于测试条件是否在循环结束时进行计算。

    do-while循环操作语句被执行至少一次,即使在条件语句的计算结果为假。

    [root@oldboy test]# awk 'BEGIN{i=1; do {print i;++i} while (i<6)}'
    1
    2
    3
    4
    5

    4.4 break,continue,exit语句

    • break 结束循环的执行
    • continue 循环内跳到循环的下一次迭代
    • exit 停止脚本的执行。接受一个整数作为参数,这将是awk进程的退出状态代码。如果没有任何参数,则返回状态为0.
    [root@oldboy test]# awk 'BEGIN{sum=0; for (i=0;i<20;++i) {sum +=i; if (sum>50) break; else print "Sum =",sum}} '
    Sum = 0
    Sum = 1
    Sum = 3
    Sum = 6
    Sum = 10
    Sum = 15
    Sum = 21
    Sum = 28
    Sum = 36
    Sum = 45
    
    [root@oldboy test]# awk 'BEGIN{for (i=1; i<=20; ++i) {if (i%2==0) print i; else continue}}'      
    2
    4
    6
    8
    10
    12
    14
    16
    18
    20
    
    [root@oldboy test]# awk 'BEGIN{sum=0; for (i=0;i<20;++i) {sum +=i; if (sum>50) exit(10); else print "Sum =",sum}}'
    Sum = 0
    Sum = 1
    Sum = 3
    Sum = 6
    Sum = 10
    Sum = 15
    Sum = 21
    Sum = 28
    Sum = 36
    Sum = 45

      [root@oldboy test]# echo $?  # 检查脚本的返回状态
      10

  • 相关阅读:
    Rock Pi开发笔记(二):入手Rock Pi 4B plus(基于瑞星微RK3399)板子并制作系统运行
    麒麟系统开发笔记(一):国产麒麟系统搭建开发环境之虚拟机安装
    linux实用技巧:在虚拟机vmware16软件上安装CentOs8.2虚拟机,重置可用源和安装输入法
    CentOS8安装Geant4笔记(三):Geant4介绍、编译、安装支持Qt5界面并运行exampleB1例程显示Qt界面
    CentOS8安装Geant4笔记(二):CentOS8安装Qt5.15.2并测试运行环境
    【图片+代码】:GCC 链接过程中的【重定位】过程分析
    嵌入式软件开发书籍推荐
    Commit Message 规范
    Android 12 适配指南——SplashScreen
    Android12 新特性及适配指南
  • 原文地址:https://www.cnblogs.com/zoe233/p/11923859.html
Copyright © 2020-2023  润新知