与sed一样,awk并不是Bash的一部分,但事实上几乎所有的Linux系统都安装了sed与awk,并且,常常见到Bash脚本里面有调用sed与awk的命令。awk是Unix/Linux下一种优秀的用于处理文本的编程语言工具。与其他大多数Linux命令不同的是,仅从名字上看,猜不出awk的功能。awk的名称来自它的三个创始人Alfred Aho、Peter Weinberger和Brian Kernighan的姓氏的首字母。
awk最基本的命令格式为:
awk对文件进行逐行扫描并处理。假设有一个文件team.txt,一共4列,内容分别为名字、工号、生日、工资,用awk可以显示这个文件的内容:
其中,$0代表awk读入的文件的每一整行内容,这里的print是awk中的命令,不是Linux命令。命令awk'{print$0}'team.txt与命令cat team.txt的效果相同,awk依次读取文件team.txt的每一行并且打印出来。
下面的命令只显示名字和工资,并加上序号:
其中,$1表示文件的第1列,即名字;$4表示第4列,即工资;NR(Number of the current Record)为awk的内置变量,表示当前记录(即当前行)的序号。
下面的例子,awk依次读取文件team.txt的每一行并输出Good morning,因为team.txt一共有四行,所以输出了四次Good morning:
通过上面的例子,可以进一步理解awk的“逐行扫描”。多数情况下,awk是文本输入驱动的。如果要输出Good morning,运行awk'{print"Good morning"}'这个没有文本输入的命令是不行的:
这个命令将没有任何输出,因为awk在等待文本输入(命令中不含有文件名,靠文本输入驱动的awk在等待键盘输入),键盘输入任何字符串,就会输出Good morning:
难道让awk做点事情必须要有文本输入驱动吗?其实也不是这样的,后面要讲到的awk的BEGIN模块可以解决这个问题。
awk支持正则表达式,基本的命令格式为:
例如,想知道工号为3578的人的信息,用如下命令,其中$2~3578表示第二列匹配3578:
想知道1971年出生的人的名字,用如下命令:
awk自身有重定向输出功能。下例中,awk取出了team.txt的第1列和第4列,另存为wage.txt文件:
前面提到了两种awk的基本命令格式,还有一种较常用的格式为:
-F后面带域分隔符,默认的域分隔符是空格。前面的几个例子中,数据的域分隔符是空格,所以awk命令都省略了选项-F。
显然,文件/etc/passwd的域分隔符是:,要查看Linux账号和对应的默认shell,用下面的命令:
实际上-F后面跟的域分隔符指的是输入域分隔符(/etc/passwd是awk命令的输入文件),输入域分隔符也可以由awk的内置变量FS指定;相应地,输出域分隔符由awk的内置变量OFS指定,它们的默认值都是空格。例如,查看Linux账号和对应的默认shell,输出的两列用#分隔:
与Perl语言一样,awk有BEGIN和END模块。简单地说,BEGIN模块总是最先执行,END模块总是最后执行。例如,可以使用BEGIN模块给team.txt加文件头:
下面使用END模块计算并打印平均工资,由结果可知,这几个人的平均工资为2975元:(www.xing528.com)
不管位置的先后,BEGIN模块最先执行,END模块最后执行。如下例所示,awk先执行BEGIN模块,打印Morning,然后读文件team.txt,该文件一共四行,所以打印了四次Mary,最后执行END模块,打印Bye:
前面讲过,在多数情况下,awk需要文本输入来驱动。在没有文本输入的情况下要想输出Good morning,可以用BEGIN模块:
awk具有与C语言十分类似的流程控制功能,如if和if/else条件控制,while、do-while和for循环,用于跳转或者退出的命令break、continue、next和exit等。例如,打印工资高于3000元的人的信息:
可知,一共有两个人的工资高于3000元。下面的例子,打印出第一个工资高于3000元的人的信息后,马上执行exit,程序退出了,所以只打印了一个人的信息:
awk有内置的数学函数,这些函数是Bash所没有的,见表8-6。
表8-6 awk的数学函数
例如,int(15.68)输出整数部分15,sqrt(3)输出3的平方根1.73205:
因为team.txt有四行,所以下面的命令打印出四个0到1之间的随机数:
awk提供了字符串处理函数,例如,index("Mississippi","is")返回子字符串is在字符串Mississippi中首次出现的位置;substr("707-555-1111",1,3)返回字符串707-555-1111从第1个到第3个字符组成的子字符串;length("abcdefghij")返回字符串abcdefghij的长度。具体执行结果如下:
awk还有其他字符串处理函数,这里就不一一列举了。
与Perl语言一样,awk提供了系统调用函数system。例如,awk调用Linux命令date,查看日期和时间:
awk还可以应用system函数调用其他shell或者Perl脚本,这为混合编程提供了方便。
前面的例子,给人一种感觉,似乎awk只有命令行形式。其实,awk也可以像Bash一样写成脚本,格式为:
下面脚本factorial_1.awk的功能是计算并打印出6到10的阶乘:
脚本factorial_1.awk中使用了格式化打印命令printf,awk的printf与C语言的printf在基本语法上几乎完全一致。
执行awk-f命令,可打印出6到10的阶乘:
如果将awk-f加入到脚本的第一行,得到脚本factorial_2.awk:
那么,直接运行factorial_2.awk脚本,即可打印出6到10的阶乘:
awk有两个与C语言类似的内置变量ARGC和ARGV,用于读取命令参数。awk还有内置数组变量ENVIRON,可用来读取当前系统的环境信息等。awk是一门脚本编程语言,内容很多,这里不展开讲解。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。