专栏首页呼延Awk入门学习

Awk入门学习

前言

由于最近的工作内容的关系,经常需要对文本文件做一些处理。每次都要写个脚本来处理实在是有点麻烦。这时候想起来很久以前稍微接触过的 AWK, 来做这个工作真的是再合适不过了。

因此,趁着这个机会,把 AWK 深入学习一点,记录在此。

概述

AWK 是一门解释型的编程语言。在文本处理领域它是非常强大的,它的名字来源于它的三位作者的姓氏:Alfred Aho, Peter Weinberger 和 Brian Kernighan。

GNU/Linux 发布的 AWK 目前由自由软件基金会(FSF)进行开发和维护,通常也称它为 GNU AWK。

awk 在下列任务中都有非常不错的发挥,本文后续也会举很多示例。

  • 文本处理
  • 输出格式化的文本报表
  • 执行算数运算
  • 执行字符串操作等等

简单来说 awk 就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

你可以将其理解为一个 linux 命令,只是使用参数以及方法多样一些。因为我们经常会在命令行直接使用它。

你也可以将其理解为一个简易的脚本语言,因为在使用过程中我们也可以写逻辑表达式等各种语句。

先来个热场的示例。

已有一个文本文件,格式如下:

前面的数字是热度,后面的字符串是搜索词。

100 阿里巴巴
200 京东
300 淘宝
400 awk 怎么使用

我们想计算,热度大于等 300 的词的热度,在总热度中的一个比例

虽然听起来有点绕,但是这是一个非常常见的需求,对应到这个示例中我们是想计算 (300 + 400 ) / ( 100 + 200 + 300 + 400), 此时我们只能打开我们的编译器,选择一门语言之后开始写代码了。其实不用。

把上面的文本内容放进 *a.txt *中,然后执行下面的 shell 命令即可,你会看到预期之中的 0.7.

awk ';sum += $1 }; END{ret = sub_sum * 1.0 / sum; print ret}' a.txt

这段脚本做了什么事情呢?

  1. 遍历每一行,按照空格为分隔符切割。
  2. 维护两个变量,每一行都将第一列的数字累加到 sum. 如果数字大于等于 300, 则将他累加到 sub_sum.
  3. 在执行结束后,将 sub_sum 和 sum 做一个除法。

怎么样,是不是比写其他 shell 或者 python 脚本快多了?

接下来将进入学习时间,我们逐个知识点的学习,看完本文,你也能这么花里胡哨的解决文本处理问题~.

基础语法

脚本语法

awk 除了可以在命令行执行之外,还可以写成脚本文件进行执行。我们大致的了解一下这个用法,之后不做详细讲解,以命令行用法为主要内容。因为文本的用户和命令行大同小异。

首先,创建一个包含脚本内容的文本文件 test.awk

{print $1 } 

然后我们用命令行执行这个脚本文件。

 awk -f command.awk marks.txt

这个其实是相当于命令行直接执行的一个扩展,当你写的脚本十分复杂(不推荐), 且需要多人合作或者共享的时候,脚本文件会是一个不错的选择。

命令行语法

awk [options] file ...

把上面脚本文件语法中的内容写到 options 即可。


上面所讲的,是 awk 是什么以及 怎么在系统中使用 awk, 接下来的内容就是 awk 自身的一些语法.

程序结构

awk 程序的思路是,逐行处理一个文件。

那么让我们想一下,当我们想要 处理一个文件的时候会需要做些什么?

  1. 进行处理之前,先初始化一些信息。
  2. 逐行处理文本,记录一些信息。
  3. 处理完之后,进行一些信息整理。比如打印,重定向等。

awk 的程序结构也是如此。

BEGIN 语句块

BEGIN {awk-commands}

BEGIN 语句块在程序开始的使用执行,它只执行一次,在这里可以初始化变量。BEGIN 是 AWK 的关键字,因此它必须为大写,注意,这个语句块是可选的。

BODY 语句块

/pattern/ {awk-commands}

BODY 语句块中的命令会对输入的每一行执行,我们也可以通过提供模式来控制这种行为。注意,BODY 语句块没有关键字。

END 语句块

END {awk-commands}

END 语句块在程序的最后执行,END 是 AWK 的关键字,因此必须为大写,它也是可选的。

所以一个添加了全部可选项的 awk 命令如下所示:

awk [options] 'BEGIN{};{};END{}' file.txt

操作符

awk 对常用的操作符都有支持,且与 c 语言使用方法一样。具体支持的操作符有:

  • 算数操作符
  • 增减运算符
  • 自增自减操作符
  • 赋值操作符
  • 关系操作符
  • 逻辑操作符
  • 三元操作符
  • 一元操作符
  • 指数操作符
  • 字符串连接操作符
  • 正则表达式操作符

流程控制

awk 支持流程控制,比如在本文最前方的示例中我们使用了 if 语句。

或者类似下面的 if 语句都是合法的。

awk 'BEGIN {
   a = 30;
   
   if (a==10)
   print "a = 10";
   else if (a == 20)
   print "a = 20";
   else if (a == 30)
   print "a = 30";
}'

循环

循环操作与其他 C 系语言一样,主要包括 for,whlie,do…while,break,continue 语句。

示例:

awk 'BEGIN {
   sum = 0; for (i = 0; i < 20; ++i) {
      sum += i; if (sum > 50) exit(10); else print "Sum =", sum 
   } 
}

内建变量

  • 0 表示正在处理的当前行
  • 1 表示当前行的第一列,以此类推,2 表示第二列。..
  • NR 表示文件中的行号,表示当前是第几行
  • NF 表示文件中的当前行被分割的列数,可以理解为 MySQL 数据表里面每一条记录有多少个字段,所以 NF 表示倒数第一格字段,(NF-1) 表示倒数第二个字段。
  • FS 表示 awk 的输入分隔符,默认分隔符为空格和制表符,可以对其进行自定义设置
  • OFS 表示 awk 的输出分隔符,默认为空格,也可以对其进行自定义设置
  • FILENAME 表示当前文件的文件名称,如果同时处理多个文件,它也表示当前文件名称
  • RS 行分隔符,用于分割行,默认为换行符
  • ORS 输出记录的分隔符,默认为换行符

内建函数

与内建变量相对应的,也有一部分的内建函数。

awk 还提供了一些内置函数,比如:

  • toupper() 用于将字符转为大写
  • tolower() 将字符转为小写
  • length() 长度
  • substr() 子字符串
  • sin() 正弦
  • cos() 余弦
  • sqrt() 平方根
  • rand() 随机数

内建函数还有一些其他的,具体可以在使用时在 man awk中查询。

自定义函数

虽然我个人是不支持用 awk 来做这么繁杂的编程工作的,但是 awk 支持我们自定义函数并且调用。语法规范如下:

function function_name(argument1, argument2, ...) { 
   function body
}

我们可以在一个 awk 脚本中放入一下内容,然后执行它。

function main(){
   print "function"
}

BEGIN {
   main()
}

常用场景示例

这里会列出一些常用的,简单的使用示例。

所有的示例都以下面的示例为输入进行运行。

1) Amit    Physics        80
2) Rahul    Maths        90
3) Shyam    Biology        87
4) Kedar    English        85
5) Hari    History        89

打印某列或者字段

AWK 可以只打印输入字段中的某些列。

$ awk '{print $3 "\t" $4}' marks.txt
Physics    80
Maths    90
Biology    87
English    85
History    89

在示例文本中,第三列包含了科目名,第四列则是得分,上面的例子中,我们只打印出了这两列,$3 和 $4 代表了输入记录中的第三和第四个字段。

打印所有的行

默认情况下,AWK 会打印出所有匹配模式的行

$ awk '/a/ {print $0}' marks.txt
2)  Rahul   Maths    90
3)  Shyam   Biology  87
4)  Kedar   English  85
5)  Hari    History  89

上述命令会判断每一行中是否包含 a,如果包含则打印该行,如果 BODY 部分缺失则默认会执行打印,因此,上述命令和下面这个是等价的

$ awk '/a/' marks.txt

打印匹配模式的列

当模式匹配成功时,默认情况下 AWK 会打印该行,但是也可以让它只打印指定的字段。例如,下面的例子中,只会打印出匹配模式的第三和第四个字段。

$ awk '/a/ {print $3 "\t" $4}' marks.txt
Maths    90
Biology    87
English    85
History    89

任意顺序打印列

$ awk '/a/ {print $4 "\t" $3}' marks.txt
90    Maths
87    Biology
85    English
89    History

统计匹配模式的行数

$ awk '/a/{++cnt} END {print "Count = ", cnt}' marks.txt
Count =  4

打印超过 18 个字符的行

$ awk 'length($0) > 18' marks.txt
3) Shyam   Biology   87
4) Kedar   English   85

查找 history 历史中,最常用的 10 个命令

history | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head

过滤文件中重复行

awk '!x[$0]++' <file>

将一行长度超过 72 字符的行打印

awk 'length>72' file

查看最近哪些用户使用系统

last | grep -v "^$" | awk '{ print $1 }' | sort -nr | uniq -c

计算文本中的数值的和

awk '{s+=$1} ENG {printf "%.0f", s}' /path/to/file

快速帮助

当你用的时候临时有忘记的或者不确定的,随时可以查看帮助命令。

man awk

完。

ChangeLog

2019-12-05 完成

以上皆为个人所思所得,如有错误欢迎评论区指正。

欢迎转载,烦请署名并保留原文链接。

联系邮箱:huyanshi2580@gmail.com

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 自定义Linux桌面,还有这么多玩法?

    您可以通过多种方法来调整Ubuntu,以自定义其外观和行为。我发现最简单的方法是使用GNOME Tweak工具,它也被称为GNOME调整或简单的调整。

    用户6543014
  • 从事软件测试应该具备的基本功底

    一般而言,操作系统类型可以分为:unix、linux、windows,咦苹果系统去哪了? 苹果系统的核是unix的一个分支。当然了要是细分下去会更多,大家大体了...

    苦叶子
  • 操作系统介绍

    操作系统(Operating System,简称OS),是管理和控制计算机硬件与资源的计算机程序,是直接运行在“裸机”上的最基础的系统软件,任何其他软件都必须在...

    胡齐
  • Linux防火墙firewalld安全设置

    防火墙是具有很好的保护作用。入侵者必须首先穿越防火墙的安全防线,才能接触目标计算机。在公司里数据安全是最重要的,要求安全部门进行全公司进行服务器防火墙安全搭建,...

    没有故事的陈师傅
  • TCP time_wait close_wait问题(可能是全网最清楚的例子)

    测试老大看到了,根据经验就推测是应该是文件句柄使用完了,应该有TCP连接很多没释放,果真发现是很多CLOSE_WAIT的状态

    千往
  • Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理

    本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看

    Java技术江湖
  • 卫星授时(网络授时服务器)源代码挥泪吐血共享

    《Linux 应用程序开发班》 / 第 8 天 -NTP 网络协议实现 /培训视频 /NTP网络协议实现 .avi 。

    NTP网络同步时钟
  • [Go] 测试go连接imap的tcp长连接

    为了保持住这条连接,每隔10秒列取一下邮件夹列表,这样就可以一直保持住连接了。开三个窗口,一个窗口不停的netstat查看tcp连接情况,一个窗口运行代码,一...

    陶士涵
  • docker--docker介绍

    在计算机的世界中,容器拥有一段漫长且传奇的历史。容器与管理程序虚拟化 (hypervisor virtualization,HV)有所不同,管理程序虚拟化通过中...

    eadela
  • star-fusion得到的融合基因结果还需要可视化哦

    其中FGFR3--TACC3这个融合基因事件我们比较熟悉了,就拿它为例子讲解如何理解这个融合现象, 首先查看具体信息:

    生信技能树

扫码关注云+社区

领取腾讯云代金券