zoukankan      html  css  js  c++  java
  • linux基础学习-18.8-awk特殊模式-BEGIN模式与END模式

    BEGIN模块再awk读取文件之前就执行,一般用来定义我们的内置变量(预定义变量,eg:FS,RS),可以输出表头(类似excel表格名称)

    BEGIN模式之前我们有在示例中提到,自定义变量,给内容变量赋值等,都使用过。需要注意的是BEGIN模式后面要接跟一个action操作块,包含在大括号内。awk必须在输入文件进行任何处理前先执行BEGIN里的动作(action)。我们可以不要任何输入文件,就可以对BEGIN模块进行测试,因为awk需要先执行完BEGIN模式,才对输入文件做处理。BEGIN模式常常被用来修改内置变量ORS,RS,FS,OFS等值。

    1、BEGIN模块

    1)第一个作用,内置变量的定义

    例1:取eth0的IP地址

    [root@www files]# ifconfig eth0|awk -F "(addr:)|( Bcast:)" 'NR==2{print $2}'
    192.168.197.133 
    [root@www files]# ifconfig eth0 | awk -F "[ :]+" 'NR==2{print $4}'
    192.168.197.133
    [root@www files]# ifconfig eth0 | awk -F "[^0-9.]+" 'NR==2{print $2}'
    192.168.197.133
    

    #上面的也可以写成

    [root@www files]# ifconfig eth0 | awk 'BEGIN{FS="(addr:)|( Bcast:)"} NR==2{print $2}'
    192.168.197.133 
    [root@www files]# ifconfig eth0 | awk 'BEGIN{FS="[ :]+"}NR==2{print $4}'
    192.168.197.133
    [root@www files]# ifconfig eth0 | awk 'BEGIN{FS="[^0-9.]+"}NR==2{print $2}'
    192.168.197.133
    

    注意:

    命令行-F本质就是修改的FS变量

    2)第二个作用,在读取文件之前,输出些提示性信息(表头)。

    [root@www files]# awk -F: 'BEGIN{print "username","UID"}{print $1,$3}' awkfile.txt 
    username UID   #这就是输出的表头信息
    root 0
    bin 1
    daemon 2
    adm 3
    lp 4
    sync 5
    shutdown 6
    halt 7
    mail 8
    uucp 10
    

    说明:

    要在第一行输出一些username和UID,我们应该想到BEGIN{}这个特殊的条件(模式),因为BEGIN{}在awk读取文件之前执行的。

    所以结果是BEGIN{print "username","UID"},注意print命令里面双引号吃啥吐啥,原样输出。

    然后我们实现了在输出文件内容之前输出“username”和“UID”,下一步输出文件的第一列和第三列即{print $1,$3}

    最后结果就是BEGIN{print "username","UID"}{print $1,$3}

    3)第三个作用,使用BEGIN模块的特殊性质,进行一些测试。

    [root@www files]#简单输出内容:
    [root@www files]# awk 'BEGIN{print "hello world!"}'
    hello world!
    [root@www files]# #进行计算
    [root@www files]# awk 'BEGIN{print 10/3}'
    3.33333
    [root@www files]# awk 'BEGIN{print 10/3+1}'
    4.33333
    [root@www files]# awk 'BEGIN{print 10/3+1/4*9}'
    5.58333
    [root@www files]# #和变量有关的操作
    [root@www files]# awk 'BEGIN{a=1;b=2;print a,b}'
    1 2
    [root@www files]# awk 'BEGIN{a=1;b=2;print a,b,a+b}'
    1 2 3
    

    4)第四种用法:配合getline读取文件,后面awk函数处讲解

    2、awk中变量的概念简介

    直接定义,直接使用即可

    awk中字母会被认为是变量,如果真的要给一个变量赋值字母(字符串),请使用双引号

    [root@oldboy files]# awk 'BEGIN{a=abcd;print a}'
    [root@oldboy files]# awk 'BEGIN{abcd=123456;a=abcd;print a}'
    123456
    [root@oldboy files]# awk 'BEGIN{a="abcd";print a}'
    abcd
    

    说明:

    没有文件awk依旧可以处理BEGIN模式下的动作(命令)

    3、END模块

    EHD在awk读取完所有的文件的时候,再执行END模块,一般用来输出一个结果(累加,数组结果),也可以是和BEGIN模块类似的结尾标识信息

    [root@oldboy files]# awk 'BEGIN{print "hello world!"}{print NR,$0}END{print "end of file"}' count.txt 
    hello world!
    1 root x root root bin bash
    2 bin x bin bin sbin nologin
    3 daemon x daemon sbin sbin nologin
    4 adm x adm var adm sbin nologin
    5 lp x lp var spool lpd sbin nologin
    6 sync x sync sbin bin sync
    7 shutdown x shutdown sbin sbin shutdown
    8 halt x halt sbin sbin halt
    9 mail x mail var spool mail sbin nologin
    10 uucp x uucp var spool uucp sbin nologin
    end of file
    

    与BEGIN模式相对应的END模式,格式一样,但是END模式仅在awk处理完所有输入行后才进行处理。

    企业案例:统计/etc/servies文件里的空行数量

    思路:

    a)空行通过正则表达式来实现:^$

    b)统计数量:

    grep -c

    awk

    方法一:grep

    [root@oldboy files]# grep "^$" /etc/services | wc -l
    16
    [root@oldboy files]# grep -c "^$" /etc/services
    16
    

    说明:

    grep命令-c表示count计数统计包含^$的行一共有多少。

    方法二:

    [root@oldboy files]# awk '/^$/{i++}END{print i}' /etc/services 
    16
    

    提示:

    使用了awk的技术功能,很常用

    第一步:统计空行个数

    /^$/表示条件,匹配出空行,然后执行{i++}(i++等于i=i+1)即:/^$/{i=i+1}

    我们可以通过/^$/{i=i+1;print i}来查看awk执行过程

    [root@oldboy files]# awk '/^$/{i=i+1;print "the value of i is:"i}' /etc/services 
    the value of i is:1
    the value of i is:2
    the value of i is:3
    the value of i is:4
    the value of i is:5
    the value of i is:6
    the value of i is:7
    the value of i is:8
    the value of i is:9
    the value of i is:10
    the value of i is:11
    the value of i is:12
    the value of i is:13
    the value of i is:14
    the value of i is:15
    the value of i is:16
    

    第二步:输出最后结果

    但是我们只想要最后的结果16,不想要过程怎么办?使用END模式输出结果

    因为END模式的特殊性质所以很适合输出最终结果

    所以最终结果就是awk '/^$/{i=i+1}END{print "blank lines count:"i}' /etc/services

    awk编程思想:

    先处理,最后再END模块输出

    {print NR,$0}body模块处理,处理完毕后

    END{print "end of file"}输出一个结果

    企业面试题:文件count.txt,文件内容是1到100(由seq 100生成),请计算文件每行值加起来的结果(计算1+...+100)

    思路:

    文件每一行都有且只有一个数字,所以我们要让文件的每行内容相加。

    回顾一下上一道题我们用的是i++即i=i+1

    这里我们需要使用到第二个常用的表达式

    i=i+$0

    对比一下,其实只是把上边的1换成了$0

    [root@oldboy files]# awk '{i=i+$0}END{print i}' count.txt

    5050

    练习题:

    1、取eth0的IP地址(BEGIN模块)

    2、统计/etc/servies文件里的空行数量

    3、BEGIN模块的三个作用

  • 相关阅读:
    如何用VSCode手动编译Ace Editor
    libuv源码分析
    二叉平衡查找树---红黑树
    tcp滑动窗口与拥塞控制
    ceph架构剖析
    腾讯面试总结
    协程的实现原理
    dhcp协议交互报文
    libuv源码分析前言
    Protobuf使用规范分享
  • 原文地址:https://www.cnblogs.com/Klanti/p/9143701.html
Copyright © 2011-2022 走看看