简明AWK实战教程

作者: 流川枫AI | 来源:发表于2018-06-15 11:56 被阅读95次
    什么编程语言的教程这么贵?

    1. 什么是AWK?

    AWK是一个强大的格式化文本处理工具,一般在类Unix操作系统中都是必带的工具(Linux、Mac OS),因此,使用无需安装,非常的方便与便捷。

    AWK其实是一种类似于shell的脚本编程语言,它支持基本的循环、遍历、判断等基本的功能,因此,你也可以像写shell脚本一样写AWK脚本,AWK也可以被理解为是一种脚本语言的解释器。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。为了掌握AWK的使用,必须掌握一些基本的AWK操作的语法。

    2. 为什么学习AWK?

    AWK与Grep、Sed并称为linux中的“三剑客”!

    三剑客的特点:
    grep:适合用于单纯的查找与匹配。
    sed:适用于编辑匹配的文本。
    AWK:适合处理格式化的文本,对文本进行复杂的格式化处理。

    你可能会问:平常我一般会用python处理格式化文本啊,为啥还学AWK?

    Maybe,针对一些大的txt文档,两者的执行效率不在一个数量级上….

    我认为AWK工具,针对较大的格式化文本数据,可能是介于pandas(便捷)与Spark(高效大数据处理能力)之间的选择,兼顾便捷与效率!

    一般AWK的效率优于Python

    还不想学~那就现实一点而!

    曾经亲身参与京东NLP算法实习生面试、百度NLP算法实习生面试,技术面试官直接问:有没有AWK的使用经验…

    JD算法工程师招聘

    所以,面试官的需求就是求职者的最高追求目标!程序猿,这需求还是得尽量满足…搞起!


    3.AWK的基本语法:

    一条完整的AWK命令由一下几部分构成:

    awk [options] 'Pattern{Action}' file

    1. awk :是AWK命令执行的关键字
    2. [options]: 是运行的一些参数项,可以省略。
    3. 'Pattern{Action}': 是命令主要部分,其中Action是核心操作,Parttern有时可以省略。
    4. file: 用于指定我们操作的格式化文本的名字,可以同时操作多个文件。

    3.1 简单介绍{Action}部分

    按照编程语言学习的惯例,先来一个AWK界的Hello Word程序:
    我们就从使用一个{Action}操作开始,指定一个打印的操作:

    awk '{print}' a.txt

    AWK输出文本中的内容

    下面我们进行一个具有实际使用价值的命令:

    df命令

    如果我们只想打印第2列的数据:

    AWK输出指定列的内容

    AWK是逐行处理格式化文本数据的,逐行的意思是,当AWK处理一个文本的时候,会一行一行的处理,处理完第一行再处理下一行,AWK默认是以换行符(回车键/ \n)标记一行的结束,新的一行的开始。

    当我们不指定文本内容的分割符的时候,awk默认把每一行的文本内容按照空格进行划分为列(当存在多个连续的空格时当做一个分割)。

    注意:AWK的第一列是从下标1开始指定的,$1代表当前行的第1个列数据,而$0是内置的变量,表示整行的内容.

    我们构建一个格式化的txt文本,内容如下:

    文本内容

    我们可以输出文本的第一列、第二列数据:

    AWK输出指定列内容

    针对某些列存在字段的缺失,AWK并不会报错,而是输出空值。

    我们可以给每一行的数据添加上一些字符串信息到制定的位置:

    AWK添加字符串输出

    awk '{print "IP统计>",$1,"数量:", $3}' test.txt

    可知,在{Action}字段内,使用双引号包裹的信息,会被当做字符串输出。

    AWK添加字符串输出

    3.2 简单介绍Pattern部分

    前面我们只是简单的介绍了{Action},下面我们简单的了解一下Pattern,也就是模式。这里我先绍两个些比较特殊的模式:BEGIN与END

    BEGIN模式:指定处理文本之前需要执行的操作
    END模式:指定了处理文本之后需要执行的操作

    awk 'BEGIN{print "IP地址","端口号”}’ test.txt

    BEGIN模式

    awk会首先指定BEGIN模式指定的命令,打印两个字符串,并不会操作test.txt文件。

    awk 'BEGIN{print "IP地址","端口号"}{print $1,$2}' test.txt

    BEGIN模式

    BEGIN模式指定的命令,在开始处理文本内容之前执行,一次类推,在处理完文本美容之后,指定END模式指定的命令。

    awk '{print $1,$2}END{print "IP地址","端口号"}’ test.txt

    END模式

    awk 'BEGIN{print "IP地址","端口号"}{print $1,$2}END{print “IP地址1",”端口号1"}' test.txt

    BEGIN+END模式

    可以同时处理文本的头、尾内容。

    3.3简单介绍Option部分

    上面我们学习了AWK中的'Pattern{Action}'部分,下面我们学习一下Option部分,即AWK命令的参数项。

    上面我们提到了AWK可以指定分隔符,默认的额分隔符是“空格”,其实分隔符也分为两类:输入分隔符、输出分隔符。

    输入分隔符:FS,用于指定输入的格式文本时,按照何种分隔符进行列的划分。
    输出分隔符:OFS,用于输出格式文本的时候,用何种分隔符进行列的划分。

    格式化文本数据

    awk -F# '{print $1,$3}’ 1test.txt

    用-F参数项指定已#为列的分隔符。

    AWK按照指定分隔符进行列的划分

    还有另外一种方式可以用于指定输入的分隔符:

    awk -v FS='#' '{print $1,$3}’ 1test.txt

    AWK按照指定分隔符进行列的划分

    同理我们可以使用-v OFS="||"参数选项英语用于指定文本的分隔符。

    awk -v FS="#" -v OFS="||" '{print $1,$3}' 1test.txt

    AWK按照指定分隔符分割列并按照指定输出分隔符输出

    再次说明一下AWK命令的形式:

    awk [options] 'Pattern{Action}' file

    -F用于指定输入的分隔符你、-V用于设置变量,都属于[Options]的一种。

    至此,我们已经简单的介绍了[options] 'Pattern{Action}' 三部分了,已经可以简单的使用AWK了。

    3.4 简单介绍一下AWK中的变量

    接下来了解一下AWK的变量:

    AWK中的变量,可以分为“内置变量”、“自定义变量”两种,其中输入分隔符、输出分隔符都属于内置的变量。

    内置变量:就是在AWK中预先定义好的、内置为AWK内部的变量。

    自定义变量:就是用户定义的变量。

    AWK的常用内置变量

    例如:NR,用来表示每一行的行号,可以在输出文本的时候显示行号:

    NR:显示每一行的行号

    NF变量则记录了每一行一共有多少列:

    NF:统计显示每一行有多少列

    此时,打印的每一行首尾的数字是对应的行一共有几列。

    3.5 使用终端输出作为AWK的输入

    除了使用AWK可以操作本机的文本数据之外,还可以直接处理其它命令行命令的输出流。

    通过使用管道命令 | ,可以直接上上一个命令的输出作为AWK数据的输入。

    AWK通过管道命令处理终端的输出流

    在上面的命令中,使用$3=="root" 表达式实现字符的匹配。

    ==实现字段完全匹配

    ~ /匹配字符/ 的比较操作,来模糊匹配第9列中存在sh字符串的行。

    ~实现字段的模糊匹配

    ~ /匹配字符/中,匹配字符还要注意关键字的转义。

    针对复杂字符串的处理,需要使用复合表达式:

    例如:

    # awk '($3 ~ /^\$[2-9][0-9]*\.[0-9][0-9]$/) && ($4=="Tech") { printf "%s\t%s\n",$0,"*"; } ' tecmint_deals.txt

    含义说明:

    • 表达式 1:($3 ~ /^\$[2-9][0-9]*\.[0-9][0-9]$/) ;查找交易价格超过 $20 的行,即只有当 $3 也就是价格满足 /^\$[2-9][0-9]*\.[0-9][0-9]$/ 时值才为真值。
    • 表达式 2:($4 == “Tech”) ;查找是否有种类为 “Tech”的交易,即只有当 $4 等于 “Tech” 时值才为真值。 切记,只有当 && 操作符的两端状态,也就是两个表达式都是真值的情况下,这一行才会被打上 (*) 标志。

    3.6 写简单的AWK脚本

    我的Mac系统里面AWK的安装目录在/usr/bin/awk下面,我们现在尝试像写shell脚本那样写一个简单的AWK脚本:

    AWK脚本

    所以,AWK也是可以编程的奥!!

    完成一个带有if-else判断的脚本:

    带判断的AWK脚本
    使用 Shell 引用:

    让我们用一个示例来演示如何在一条 awk 命令中使用 shell 引用来替代一个 shell 变量。在该示例中,我们希望在文件 /etc/passwd 中搜索一个用户名,过滤并输出用户的账户信息。

    AWK脚本3awk.sh的内容:
    #!/bin/bash

    ### 读取用户名
    
    read -p "请输入用户名:" username
    
    ### 在 /etc/passwd 中搜索用户名,然后在屏幕上输出详细信息
    
    cat /etc/passwd | awk "/$username/ "' { print $0 }’
    
    使用Shell变量
    使用 awk 进行变量赋值

    也可以通过定义AWK自变量的方式实现上面的功能:

    使用AWK自变量

    注意:
    分析一下 awk 脚本 ' $0 ~ name {print $0}' 中的 $0 ~ namevalue ~ pattern 便是比较运算符之一,它是指:如果 value(匹配的内容区域) 匹配了 pattern(需要被匹配的内容) 则返回 true。进而该部分通过匹配的行信息会在{Action}命令中继续进行处理。

    Next命令

    next命令在编写高效的命令脚本时候是非常重要的,它可以提高脚本速度

    awk '$3 > 10 { print $0,"大于10" ; next; } $3<10 { print $0,"小于10"} ' test.txt

    Next命令

    当输入行用命令'$3 > 10 { print $0,"大于10" ; next; } 打印以后,next命令将跳过第二个$3<10 { print $0,"小于10"}表达式的判断,继续判断下一个输入行,而不是浪费时间继续判断一下是不是当前输入行还小于10。

    4. 总结

    以上只是简单的介绍了AWK的使用,这只是AWK强大功能的冰山一角,更详细的教程推荐!AWK在工业界的处理格式化文本数据的场景中具有广泛的使用,尤其是NLP相关的算法工程师,针对线上的大数据我们可能直接借助公司的Spark数据平台来处理,但针对线下的一些较大的格式化文本数据,AWK脚本语言或许是一个不错的选择!

    推荐参考:

    Linux 三剑客:

    相关文章

      网友评论

        本文标题:简明AWK实战教程

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