背景
awk语言,出自三位创始人姓氏的首字母(Alfred Aho 、Peter Weinberger 和 Brian Kernighan)。在2011年针对发起者Alfred Aho的采访中,问起为何会创作了awk语言,Alfred的回答是在上世纪80年代初,为了追踪经费预算或者追踪学生的成绩,同时避免用C或者其它语言长篇的语句来实现,所以创造了awk语言,旨在用少量的代码行数就能实现如此的功能。同样,与后期Larry Wall创作了Perl语言一样,这些大师们出于某个实际应用,又不想写一堆代码,所以正是在这种程序员独有的“懒惰”与“完美主义”的双重人格下,极简而又优雅的语言,就被创造了出来。
awk是一种优良的文本处理工具,它不仅是 Linux 中也是任何环境中现有的最强大的数据处理引擎之一,提供了极其强大的功能:样式装入、流控制、数学运算符、进程控制语句等等。而且内置了许多变量和函数,可以便于使用者在用awk处理文本的时候,简洁而又方便得通过少量代码就能获取所需信息。
格式
在awk中,格式会严重影响输出的正确性,通常而言,两种常见的格式如下:
awk '{pattern + action}' input_file awk 'pattern {action}' input_file
比如说,如果文件中第一列匹配关键字abc,那就打印最后一列:
-
第一种格式,awk '{if($1 ~ /abc/) print $NF}' input_file
-
第二种格式,awk '$1 ~ /abc/ {print $NF}' input_file
参数
通常情况下, awk命令常用参数有-F与-v
-F 输入内容的分隔符(field)
-v 某个可以传入的参数(var=val)
比如输入内容分隔符是竖线(|),如果要打印每一行的列数,可以运行
awk -F '|' '{print NF}' input_file
如果要通过-v打印出“列数是”的关键字,可以运行
awk -F '|' -v 'dp=列数是' '{print dp, NF}' input_file
特殊变量
细心的读者在上述用例中,已经发现了NF这样的关键字,其实在awk中,除了NF,还有很多其它类似的特殊变量:
-
$0:代表整行
-
$1:代表分隔后第一列;同理$2代表第二列,以此类推
-
NF:number of fields,代表一行中列的个数,所以$NF表示最后一列
-
NR:number of rows,代表该行的行号
-
FS:field separator,代表输入文件的列分隔符
-
OFS:output field separator,代表输出内容的列分隔符
所以,如果要打印某个文件的第2行,通过awk可以如下执行:
awk 'NR == 2 {print}' input_file #通过格式二书写
如果要将input_file(分隔符是'|')的第一列替换成test:
awk -F '|' '{$1="test";print}' input_file
细心的读者同样也会发现,输出内容的分隔符与原始文件不一致,所以如果要将上述输出内容依旧保持文件最开始的分隔符'|':
awk -F '|' '{$1="test";OFS=FS;print}' input_file
内置函数
为了文字处理更加便捷,awk开发了一系列的内置函数,通过这些函数能极大简化代码的行数,本文选取常用函数进行介绍:
-
length,长度
-
gsub,替换
-
substr,截取
-
split,分隔
length
例如,用'|'作为分隔符,将input_file文件每一行的长度以及第二列的长度打印出来:
awk -F '|' '{print length,length($2)}' input_file
注:上述length如果代表的是一行长度,会包括分隔符'|'
gsub
对gsub函数而言,有两种格式,分别是:
-
gsub("a","b"),将单行中所有的"a"替换为"b"
-
gsub("a","b",sth),将sth中所有的"a"替换为"b"
比如,如果要将input_file中,所有的"i"字符,替换为"%",可以运行:
awk -F '|' '{gsub("s","%");OFS=FS;print}' input_file
如果要将第二列的所有的"s"替换为"%",可以运行:
awk -F '|' '{gsub("s","%",$2);OFS=FS;print}' input_file
substr
与gsub类似,substr也有两种格式
-
substr(sth,num),将sth从num开始截图到最后
-
substr(sth,num1,num2),将sth从num1开始往后截取num2位
注:上述sth可以是某个字符串,也可以是某个变量或者$1/$2这样某一个列
例如将以'|'作为分隔符的第一列,从第2位开始截取到最后:
awk -F '|' '{a=substr($1,2);print a}' input_file
或者从第2位开始往后截取2位:
awk -F '|' '{a=substr($1,2,2);print a}' input_file
split
split主要作用是将某一串字符串,根据某个关键字来分隔,并将分割完的结果保存到某个数组中,格式如下:
-
split(sth,数组名,"分隔符")
表示将sth按照“分隔符”切分,并将切分后的结果保存到数组“数组名”中。
比如将字符串"this|is|a|test"按照"|"切分,并打印第二部分内容
echo "this|is|a|test" | awk '{split($0,arr,"|");print arr[1]}'
注:上述arr为人为定义的一个数组名称,并且数组的下标从1开始
运算与判断
在任何一门编程语言中,离不开各式各样的运算以及判断,awk支持多种运算,这些运算与C语言提供的基本相同:如+、-、*、/、%等等,同时awk也支持C语言中类似++、--、+=、-=、=+、=-之类的功能,这给熟悉C语言的使用者编写awk程序带来了极大的方便。作为对运算功能的一种扩展,awk还提供了一系列内置的运算函数(如log、sqr、cos、sin等等)和一些用于对字符串进行操作(运算)的函数(如length、substr等等)。这些函数的引用大大的提高了awk的运算功能。
在判断上,awk也提供了相当多功能,如常用的==(等于)、!=(不等于)、>(大于)、>=(大于等于)、