专栏首页AI星球简明AWK实战教程

简明AWK实战教程

什么编程语言的教程这么贵?

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 awk -F "[\t]" '{print $1}' aa.txt //指定以tab为每行的分隔符

用-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 { print0,"大于10" ; next; } 3<10 { print0,"小于10"} ' test.txt

Next命令

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

*AWK统计文件中某关键词出现次数

1、统计文件test.txt中第2列不同值出现的次数

awk '{sum[$2]+=1}END{for(i in sum)print i"\t"sum[i]}'  test.txt

如文件test.txt第2列的值为"00""01"或"02",执行结果如下:

[root@localhost cc]# cat test.txt
a 00
b 01
c 00
d 02
[root@localhost cc]# awk '{sum[$2]+=1}END{for(i in sum)print i"\t"sum[i]}' test.txt
00 2
01 1
02 1
[root@localhost cc]#

2、如只统计文件test.txt中第2列"00"或"01"出现的次数,命令可写为

awk '{if($2=="00") ++sum1;if($7=="01") ++sum2}END{print "00""\t"sum1"\n""01""\t"sum2}' test.txt

执行结果如下:

[root@localhost cc]# awk '{if($2=="00") ++sum1;if($2=="01") ++sum2}END{print "00""\t"sum1"\n""01""\t"sum2}' test.txt
00 2
01 1

4. 总结

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

推荐参考:

Linux 三剑客:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 机器学习入门资源

    这是我在开始学习机器学习的知识的时候,看到的一个比较不错的基础学习路径教程以及部分学习资源。

    流川枫
  • Java Web 从入门到"改行"(2)--Servlet简介

    JavaWeb应用开发的核心技术就是JSP、Servlet与JavaBean。Servlet 作为 Java Web 应用开发的核心技术之一,JSP 以及其他很...

    流川枫
  • JavaScript的10张总结性思维导图

    学习技术的道路上还是需要不断总结归纳的,在浏览微信公众号的的时候,偶然发现了10张javascript相关的思维导图。

    流川枫
  • python开发_dbm_键值对存储_完整_博主推荐

    ============================================

    Hongten
  • 30 分钟快速入门 Docker 教程

    在没有 Docker 的时代,我们会使用硬件虚拟化(虚拟机)以提供隔离。这里,虚拟机通过在操作系统上建立了一个中间虚拟软件层 Hypervisor ,并利用物理...

    用户2781897
  • 15 分钟掌握 15 个 Docker 小窍门

    1. 获取最近运行容器的id 这是我们经常会用到的一个操作,按照官方示例,你可以这样做(环境ubuntu): $ ID=$(docker run ubuntu...

    小小科
  • Docker安装

    这时候启动Docker时发现存储目录依旧是/var/lib/docker,但是实际上是存储在数据盘的,你可以在数据盘上看到容量变化。

    剑行者
  • 如何优雅使用Docker?请收下这15个小技巧。

    获取最近运行容器的id 这是我们经常会用到的一个操作,按照官方示例,你可以这样做(环境ubuntu):

    黄泽杰
  • docker

    我们在build镜像的过程中,可能会产生一些临时的不具有名称也没有作用的镜像他们的名称一般都是<none>,我们可以执行下面的命令将其清除掉:

    用户1499526
  • Docker 命令总结

    小手冰凉

扫码关注云+社区

领取腾讯云代金券