美文网首页
gawk基础

gawk基础

作者: 御浅永夜 | 来源:发表于2018-01-21 22:46 被阅读0次

    前言

    本文并不是一篇gawk手册一样的文章,所以不可能条理清楚的告诉你如何使用,而是循序渐进的描述自己对这个工具的掌握。
    gawk表现的更像一门语言,像使用一门语言那样的使用它的基本操作就能达到我自己的需求了。

    1. 拆分、选择

    我们大概什么时候使用gawk呢?就我自己来说,就是对一个文件的每一行按照分隔符拆分成多个元素,然后选取自己需要的,即拆分、选择。

    例如下面的一个文件test.file(姓名:学号:成绩)

    Alice:1:98
    Bob:2:70
    

    使用gawk程序的基本格式:gawk option program file
    option->-F::指定分隔符,通过:将每一行分隔
    program->'{print $1}':打印出分隔出来的元素1
    file->test.file:指定输入文件,如果未指定,则从STDIN等待输入

    renz@renz-ubuntu:~/work$ gawk -F: '{print $1}' test.file
    Alice
    Bob
    renz@renz-ubuntu:~/work$ gawk -F: '{print $2}' test.file 
    1
    2
    renz@renz-ubuntu:~/work$ gawk -F: '{print $3}' test.file 
    98
    70
    

    gawk以文件的每行为一个单位,Alice:1:98:分为Alice198,拆分的元素可以通过$1、$2、$3取出。

    2. 多重拆分、选择

    得益于可以在程序中使用多个命令命令1 | 命令2,我们可以对已经拆分的结果再次拆分,这使我可以应对稍复杂的内容。

    例如class.xml文件:

    <class>
        <students>
            <student>
                <name>Alice</name>
                <serial>1</serial>
                <score>98</score>
            </student>
            <student>
                <name>Bob</name>
                <serial>2</serial>
                <score>70</score>
            </student>
        </students>
    </class>
    

    我想打印出所有同学的名字,策略就是先通过name分隔为< >Alice</ >即$1=' <',$2='>Alice<',$3='>'

    renz@renz-ubuntu:~/work$ gawk '{FS="name"; print $2}' class.xml 
    
    
    
    
    >Alice</
    
    
    
    >Bob</
    
    
    
    
    

    然后对$2通过>分隔为$1='',$2='Alice<'

    renz@renz-ubuntu:~/work$ gawk '{FS="name"; print $2}' class.xml | gawk '{FS=">"; print $2}'
    
    
    
    
    Alice</
    
    
    
    Bob</
    
    
    
    
    

    然后再对$2通过<分隔为$1='Alice',$2=''。

    renz@renz-ubuntu:~/work$ gawk '{FS="name"; print $2}' class.xml | gawk '{FS=">"; print $2}' | gawk '{FS="<"; print $1}'
    
    
    
    
    Alice
    
    
    
    Bob
    
    
    
    
    

    3. 变量与循环结构的使用

    3.1 为什么要使用变量

    上一例中的xml文件完美到强迫症的人都会觉得舒服,因为是专门排版给人看的,未经过排版的class2.xml文件如下:

    <class>
        <students>
            <student><name>Alice</name><serial>1</serial><score>98</score></student><student><name>Bob</name><serial>2</serial><score>70</score></student>
        </students>
    </class>
    

    这个文件的结构对于使用xpath解析来说没有任何影响,但是对于使用gawk解析的我来说

    renz@renz-ubuntu:~/work$ gawk '{FS="name"; print $2}' class2.xml | gawk '{FS=">"; print $2}' | gawk '{FS="<"; print $1}'
    
    
    Alice
    
    
    

    Bob不见了!
    原因在于第二次解析的时候,Bob在$4中,而我们只解析了$2。

    renz@renz-ubuntu:~/work$ gawk '{FS="name"; print $1,$2,$3,$4,$5}' class2.xml
    <class>    
        <students>    
            <student><serial>1</serial>< >Alice</ ></student><student><serial>2</serial>< >Bob</ ></student>
        </students>    
    </class>    
    

    于是我们只要改变策略就可以了:

    学生数 解析的参数
    1 $2
    2 $2,$4
    3 $2,$4,$6
    ... ...
    n $2,$4,...,$2n

    但是<student>是一个可以无限制添加的节点啊,每多一个学生就要修改一下程序吗?
    在工作中我遇到这种情况的时候,内心是崩溃的。于是经验不足的我产生了一个大胆的想法,gawk能不能够告诉我它究竟分隔了多少个元素,这样我就可以通过循环来确定每次要解析的元素。

    我就是这样查到了gawk的高级特性。

    3.2 如何使用变量

    两种不同类型的变量:

    1. 内建变量
    2. 自定义变量

    3.2.1 内建变量

    字段和记录分隔符变量
    内建变量是用来使用程序里的特定功能的,解决诸如我们用什么来分隔字符串,再以怎样的格式显示出来。

    变量 描述
    FS 输入字段分隔符
    OFS 输出字段分隔符(默认空格)

    数据变量
    用来掌控环境变化的,还可以提取shell环境的信息。

    变量 描述
    ARGC 命令行参数个数
    ARGV 包含命令行参数的数组
    FILENAME 用作gawk输入数据的数据文件的文件名
    NF 数据文件中的字段总数

    还记得我最开始的需求吗,我需要知道按照分隔符到底分了多少个字段,这样我就可以根据分隔的字段总数来选取解析的参数,NF就可以帮助我完成这件事。我们只需解析偶数,一直解析到NF-1就能不管一行有多少,都能遍历取出了:

    renz@renz-ubuntu:~/work$ awk '{FS="name"; i=2;while (i<NF){ print $i;i++;i++} }' class2.xml | gawk '{FS=">"; print $2}'
    
    Bob</
    

    然而出了点问题,太尴尬了,毕竟我也是新手。但是上面的例子同时展示了两个新的特性——自定义变量循环结构,这就是为什么我们可以把他当作一门语言来学的原因,对了,后面将学到还可以声明函数:)。

    3.2.2 自定义变量

    3.3 结构化语句

    3.4 函数

    相关文章

      网友评论

          本文标题:gawk基础

          本文链接:https://www.haomeiwen.com/subject/ojfqaxtx.html