zoukankan      html  css  js  c++  java
  • 初识gawk, gawk Notes(1)

    第一次看见awk这三个字母,是在某实习童鞋的QQ状态里面,赞同事写的awk如何高效。

    昨天在书畅草草看了下IBM官方技术博里的文章,觉得很赞,很激动,但是有点看不太懂,还是自己抱着教科书,老老实实从头看起吧。

    哦,这里说一下,最近看的shell相关的东西,都是跟着《A Pratical Guide to Linux Commands,Editors, and Shell Programming》这本书的。

    gawk是awk的GNU版本。

    > 使用条件

    主要是用gawk来处理结构化的数据。

    什么是结构化呢,我的理解,就是一个文件里面的内容,可以按照某种记录记录格式,一条记录一条记录地读,同时,每一条记录中间用一个分隔符分成了若干个部分,而且所有记录用同一个分隔符,且所有行用分隔符分出来的部分的数目相同。

    当然,gawk可以结构化数据,也可以输出结构化数据。

    另外,要提的一点是,gawk在处理数据的时候,不修改原有的数据文件,只是将数据读出来,做处理。

    > 语法

    gawk [option] [program] [file-list]

    gawk [options] –f program-file [file-list]

    白话说来,运行gawk有两种方式:

    1、直接在shell里面运行。option是运行的选项;program是gawk的代码,要用' ' 括起来,目的是屏蔽shell对里面内容的解析;file-list是用到的数据文件。[option 有哪些?file-list多个文件怎么处理?]

    2、将gawk作为独立的文件,调用gawk文件来执行。要用-f来标记是使用的gawk文件,同时program-list是gawk文件的列表。

    > 选项(option)

    仅列出要紧的几个

    -F fs 将fs作为输入字段分隔符
    -f program-file 从program-file 命名文件而不是标准输入读取gawk程序,用户可以多次指定这个选项
    -v var=value 将value赋值给var。赋值动作在gawk程序执行之前进行,并用于BEGIN模式。可以在命令行上多次指定这一选项。

    > 组成单元

    好吧,这是我根据自己理解用的一个名词。为什么这么说呢?想想以前的各种语言,C,基本组成单元是函数,除了头文件之外,程序是有各个函数构成的;C++类似;Java,各种方法,所以说,他们的组成单元是 函数 或 方法。

    但是gawk呢?如下:

    pattern{ action }

    每个action用 "{","}"包围起来,同时,"{"要跟在pattern的同一行

    pattern有多种,action各式各样,但是整个gawk的程序,可以按照这样的组成单元,分解开来。

    所以说,写gawk程序,就是在源文件里面,构建一个个这样的组成单元。

    gawk的组成单元,有两个部分,pattern,action。pattern作为一个模式,决定了action在什么情况下运行,而action,则是当记录符合条件(pattern)时,执行什么样的动作。这里想用一个图来说明下:

    image

    图1 gawk处理结构化数据示意图

    如图1所示,gawk的程度,就像是在结构数据上的套子,顺着结构数据,从头读到尾,然后根据数据是否满足要求,来决定执行action。这里有一个问题,在gawk文件内,多个组成单元,是怎么样的一个执行顺序,在后面会用实例检验一下。

    根据pattern的不同,可以讲组成单元分成3类:

    1、系统默认

    有两个BEGIN,END。

    BEGIN在所有代码开始前执行,也就是说,他不参与pattern的判定。主要是用来初始化一些系统变量等。

    END在前面的所有代码执行完毕后执行,也没有pattern的判定。主要是清理一些中间生成的临时数据等等。

    2、无pattern

    也就是pattern为空,表示所有的结构化数据,每行数据,都要执行这个pattern下的action

    3、定义pattern

    实际上“定义pattern”和“无pattern”一样,action都是用户来写的,这里之所以区分开,如前面所说,是基于pattern来分的。

    这一类,pattern可以是一个条件判断,也可以是一个正则表达式匹配。

    > 系统变量

    这些变量被gawk占用了,用的时候,直接拿来就是对应的含义:

    表1 变量

    $0 当前记录(作为单个变量)
    $1-$n 当前记录中的字段
    FILENAME 当前输入文件名
    FS (Field Split)输入字段字段分隔符
    NF (Number of Fields)当前记录的字段数目
    NR (Number of current Record)当前记录的记录编号
    OFS (Output Field Split)输出字段分隔符(默认为空格)
    ORS (Output Record Split)输出记录分隔符(默认为换行符)
    RS (Record Split)输入记录分隔符(默认为换行)

    FS,RS,可以在BEGIN中,根据具体输入文件的不同,进行设置。

    OFS,ORS,也可以再BEGIN中,根据输出文件的要求,进行设置。

    在程序中,可以通过NF,知道一条记录中有多少个字段,也就决定了$1-$n的n是多少。

    任何时刻都可以修改分隔符的值,具体方法是通过在程序中或者在命令行中使用--assign(-v)选项,将一项新的值指派给对应的变量。

    (也就意味着,在输入和输出文件中,都可以出现分隔符不同一的情况)

    > 函数

    gawk的内置函数,用来操作数字和字符串

    表2 函数

    length(str) 返回字符串str的字符个数,如果没有参数str,返回当前记录的字符个数
    int(num) 返回num的整数部分
    index(str1,str2) 返回str2在str1中的位置,如果str2不存在返回0
    split(str,arr,del) 用del做分隔符,将str的元素放置到arr[1]到arr[n]中,返回数组元素个数
    sprintf(fmt,args) 根据fmt格式化args并返回格式化后的字符串
    substr(str,pos,len) 返回str中从pos开始长度为len个字符的字符串
    tolower(str) str字母全部转为小写
    toupper(str) str字母全部转为大写

    > 注释

    该行以 # 开头。

    > 关联数组

    我理解它类似于C#的Dictionary<k,v>,可以用字符串做索引:array[string]=value

    在使用的时候,利用for可以实现:for (elem in array) print array[elem]

    > 控制结构

    if-else,while,for 与C语言的对应项基本一致,完全不同于Shell下的对应项,不再赘述。

    初始gawk,就到这里,用一个例子来结束:

    数据文件cars记录了一组关于汽车的销售信息(品牌,型号,生产年代,千里里程数,价格),用gawk,写程序,统计下平均使用年限,所有车的平均价格和新车(晚于2000年)的平均价格

    image

    图2 数据文件cars

    image

    图3 gawk代码

    image

    图4 运行结果

  • 相关阅读:
    jQuery动画速成
    elementui更改导航栏样式
    Python反射
    Linux基础--基本命令
    Linux基础--简介
    DRF
    Socket与Websocket初识
    五星宏辉游戏项目小结
    Redis详解(8)--redis-cluster
    Redis详解(7)--主从复制
  • 原文地址:https://www.cnblogs.com/YFYkuner/p/2669803.html
Copyright © 2011-2022 走看看