在Linux操作系统中,grep、sed、awk被称为文本操作"三剑客",上两期中,我们将详细介绍grep、sed的基本使用方法,希望能够帮助到有需要的朋友,现在,我们继续学习awk。
虽然awk是一个Linux中常见的命令,但确切的说,awk是一门编程语言。
要讲起来真的十分复杂,网上有很多教程,讲的都很棒的,但是也讲得很迷糊。
我也是在摸索中学习,尽量讲清晰一些,希望您在看的过程中,能够有所发现。
首先上官方手册:Gawk - GNU Project - Free Software Foundation (FSF)
1、awk简介
gawk - pattern scanning and processing language(模式扫描和处理语言)。AWK 的名称是由它们设计者的名字缩写而来 ------Afred Aho, Peter Weinberger与Brian Kernighan。
1.1 语法
awk [options] file ...
gawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...
gawk [ POSIX or GNU style options ] [ -- ] program-text file ...
pgawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...
pgawk [ POSIX or GNU style options ] [ -- ] program-text file ...
dgawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...
可以看到,awk有几种版本,包括GAWK、pgawk、dgawk 。GAWK完全兼容 AWK 与 NAWK
1.2 描述
gawk 是 GNU 项目对 AWK 编程语言的实现。它符合 POSIX 1003.1 标准中对该语言的定义。该版本又基于 Aho、Kernighan 和 Weinberger 合著的《AWK 编程语言》一书中的描述。gawk 提供了当前版本 UNIX awk 中的一些附加功能以及许多 GNU 特有的扩展。命令行由 gawk 自身的选项、AWK 程序文本(如果没有通过 -f 或 --file 选项提供)以及要在预定义 AWK 变量 ARGC 和 ARGV 中使用的值组成。
pgawk 是 gawk 的性能分析版本。除了程序运行速度较慢并且在完成后自动在 awkprof.out 文件中生成执行性能分析报告之外,它在其他方面都与 gawk 完全相同。请参阅下面 --profile 选项的说明。
dgawk 是一个 awk 调试器。它不会直接运行程序,而是加载 AWK 源代码,然后提示输入调试命令。与 gawk 和 pgawk 不同,dgawk 只处理使用 -f 选项提供的 AWK 程序源代码。调试器在《GAWK: 高效 AWK 编程》一书中有详细介绍。
1.3 工作流程
awk语言的工作流程如上所示,分为三块为:BEGIN块、BODY块和END块。
BEGIN块开始,循环执行BODY块,最后执行END块。
开始块(BEGIN block)
开始块的语法格式如下所示:
BEGIN {awk-commands}
程序启动执行BEGIN块代码部分,BEGIN块在整个过程中只执行一次。BEGIN 是 AWK 的关键字,因此它必须是大写的。BEGIN块是可选的,可以没有BEGIN块部分。注意,awk代码块使用 {} 花括号整合一个块。
主体块(Body Block)
主体部分的语法要求如下:
/pattern/ {awk-commands}
对于每一个输入的行都会执行一次主体部分的命令。默认情况下,对于输入的每一行,AWK 都会很执行命令。但是,我们可以将其限定在指定的模式中。 注意,在主体块部分没有关键字存在。
结束块(END Block)
下面是结束块的语法格式:
END {awk-commands}
结束块是在程序结束时执行的代码。 END 也是 AWK 的关键字,它也必须大写。 与开始块相似,结束块也是可选的。
1.4 一个简单的例子
先创建一个名为 file1.txt 的文件。
Jan 13 25 15 115
Feb 15 32 24 226
Mar 15 24 34 228
Apr 31 52 63 420
May 16 34 29 208
Jun 31 42 75 492
Jul 24 34 67 436
Aug 15 34 47 316
Sep 13 55 37 277
Oct 29 54 68 525
Nov 20 87 82 577
Dec 17 35 61 401
使用下面的awk代码,
$ awk 'BEGIN{printf "月份\t年\t日\t年份\t版本\n"} {print}' file1.txt
执行以上命令,输出结果如下:
月份 年 日 年份 版本
Jan 13 25 15 115
Feb 15 32 24 226
Mar 15 24 34 228
Apr 31 52 63 420
May 16 34 29 208
Jun 31 42 75 492
Jul 24 34 67 436
Aug 15 34 47 316
Sep 13 55 37 277
Oct 29 54 68 525
Nov 20 87 82 577
Dec 17 35 61 401
对于这句代码,awk'BEGIN{printf "月份\t年\t日\t年份\t版本\n"} {print}' file1.txt,我们简单解释一下:
程序开始执行时,AWK 在开始块中读到了"BEGIN" 这个关键词,执行花括号里面的内容,输出表头信息。在主体块中,AWK 每读入一行就将读入的内容输出至标准输出流中,一直循环到整个文件被全部读入为止。
awk | 程序指令 |
---|---|
' ' | awk程序块 |
BEGIN | 开始块 |
{...} | awk开始块的程序 |
printf | 指定格式输出 |
" " | printf的输出内容 |
\t | 制表符 |
\n | 换行符 |
{print} | 主体块,简单输出 |
这里还涉及到两个知识点,printf和print
这里大概讲一下,前面的 printf 是为了控制宽度、精度采用,而后面的 print 只需要简单的输出数据而已。
2、awk常用参数
常用参数:
-c:使用兼容模式
-C:显示版权信息
-e:指定源码文件
-f:从脚本中读取 awk 命令
-F:设置输入时的字段分隔符
-v:自定义变量信息
-h:显示帮助信息
-m:对指定值进行限制
3、awk的变量
ARGC
表示在命令行提供的参数的个数。
ARGV
这个变量表示存储命令行输入参数的数组。数组的有效索引是从 0 到 ARGC-1。
CONVFMT
此变量表示数据转换为字符串的格式,其默认值为 %.6g。
ENVIRON
此变量是与环境变量相关的关联数组变量。
FILENAME
此变量表示当前文件名称。
FS
此变量表示输入的数据域之间的分隔符,其默认值是空格。 你可以使用 -F 命令行选项改变它的默认值。
NF
此变量表示当前输入记录中域的数量。
NR
此变量表示当前记录的数量。(译注:该变量类似一个计数器,统计记录的数量)
FNR
该变量与 NR 类似,不过它是相对于当前文件而言的。此变量在处理多个文件输入时有重要的作用。每当从新的文件中读入时 FNR 都会被重新设置为 0。
OFMT
此变量表示数值输出的格式,它的默认值为 %.6g。
示例:
还是原来file1.txt这张表:
Jan 13 25 15 115
Feb 15 32 24 226
Mar 15 24 34 228
Apr 31 52 63 420
May 16 34 29 208
Jun 31 42 75 492
Jul 24 34 67 436
Aug 15 34 47 316
Sep 13 55 37 277
Oct 29 54 68 525
Nov 20 87 82 577
Dec 17 35 61 401
对于awk而言,变量就是列,用$符号来表示,比如下面的内容:
$ awk '{print $1}' file1.txt
这里 $1,表示输出第一列,输入如下:
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
要是使用下面的代码:
$ awk -F: '{print $1}' file1.txt
输出:
Jan 13 25 15 115
Feb 15 32 24 226
Mar 15 24 34 228
Apr 31 52 63 420
May 16 34 29 208
Jun 31 42 75 492
Jul 24 34 67 436
Aug 15 34 47 316
Sep 13 55 37 277
Oct 29 54 68 525
Nov 20 87 82 577
Dec 17 35 61 401
这里,-F:设置输入时的字段分隔符。
要是使用下面的代码:
$ awk -F: '{print $1,$NF}' file1.txt
输出:
Jan 13 25 15 115 Jan 13 25 15 115
Feb 15 32 24 226 Feb 15 32 24 226
Mar 15 24 34 228 Mar 15 24 34 228
Apr 31 52 63 420 Apr 31 52 63 420
May 16 34 29 208 May 16 34 29 208
Jun 31 42 75 492 Jun 31 42 75 492
Jul 24 34 67 436 Jul 24 34 67 436
Aug 15 34 47 316 Aug 15 34 47 316
Sep 13 55 37 277 Sep 13 55 37 277
Oct 29 54 68 525 Oct 29 54 68 525
Nov 20 87 82 577 Nov 20 87 82 577
Dec 17 35 61 401 Dec 17 35 61 401
这里,NF此变量表示当前输入记录中域的数量。
还有很多内容,包括循环、条件、运算、函数等,篇幅有限,看后期大家是否需要,如果需要的话,关注我,联系我更新。
如果您觉得有些用处,欢迎在评论区留言,关注。谢谢您的阅读!
往期学习笔记: