Awk教程
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Awk教程相关的知识,希望对你有一定的参考价值。
Awk教程
一、awk 简介
awk是一种解释执行的编程语言,专门用来处理文本数据的。
二、awk工作流程:
Awk内部工作原理;AWK执行的流程非常简单:读( Read )、执 行( Execute )与重复( Repeat );下面是流程图:
Awk工作流程图
读( Read ):AWK 从输入流(文件、管道或者标准输入)中读入一行然后将其存入内存中。
执行(Execute):对于每一行输入,所有的
重复(Repeate):一直重复上述两个过程直到文件结束。
awk程序结构
Awk程序结构主要包括三块:BEGIN(开始块)、主体块、END(结束块);
开始块(BEGIN BLOCK):
语法:
BEGINawk-commands
开始块就是awk程序启动时执行的代码部分(在处理输入流之前执行),并且在整个过程中只执行一次;一般情况下,我们在开始块中初始化一些变量。BEGIN是awk的关键字,因此必须要大写。【注:开始块部分是可选,即你的awk程序可以没有开始块部分】
主体块(Body Block):
语法:
/pattern/awk-commands
针对每一个输入的行都会执行一次主体部分的命令,默认情况下,对于输入的每一行,awk都会执行主体部分的命令,但是我可以使用/pattern/限制其在指定模式下。
结束块(END BLOCK):
语法:
ENDawk-commands
结束块是awk程序结束时执行的代码(在处理完输入流之后执行),END也是awk的关键字,必须大写,与开始块类似,结束块也是可选的。
示例1:
题目:有一个文本a.txt,内容如下:
1 zhengchengcheng math 100
2 wangbin chinese 80
3 wangcheng pgysical 85
4 lily english 75
5 mary history 90
使用awk将其标准输出并附带表头信息?
解答:
awk基本语法
Awk命令行模式:
一般情况下,我们使用awk命令行模式比较多,即直接使用awk命令处理文本数据;
Awk命令行格式如下:
awk [options] ‘awk-commands’ file
Awk程序文件:
当然,除了直接使用awk命令来处理文本之外,我们还可以将awk命令写成脚本来执行,即awk程序文件。
Awk程序文件执行格式如下:
awk [options] -f file
Awk标准选项:
常用的awk选项如下:
-v:这个选项可以为变量赋值,它允许在程序执行之前为变量赋值【注:一般用法即在程序执行前为变量赋值】
例如:
执行结果如下:
--dump-variables[=file]:此选项会将awk全局变量及相应值按序输出到指定文件中,不指定文件,默认输出文件名是awkvars.out
执行结果如下:
awk --dump-variables=/tmp/xin 【注:’’引号不能少,不然会报错,代表awk主体部分;--dump-variables=/tmp/xin表示将内容输出到/tmp/xin文件中去】
--lint[=fatal]:这个选项用于检测程序的可移植情况以及代码中的可以部分,如果提供了参数fatal,awk会将所有的警告信息当错误信息输出。
例如:awk --lint /tmp/xin 【注:同样,强调一遍,主题部分不能省略,没处理命令使用’’代替即可,检测文件为/tmp/xin】
执行结果如下:
--profile[=file]:此选项会将程序文件以一种很优美的格式输出(常用来格式化awk脚本文件),默认输出文件是awkprof.out,[=file]表示将格式化后的脚本内容输出到指定文件。
例如:awk -F" " --profile=/tmp/awk.sh BEGINprintf "No\\tName\\t\\tCourse\\tGrade\\n\\n" print $0 ENDprint"\\n-----The End-----" a.txt 【注:使用awk格式化输出a.txt内容,并将命令以一种优美的方式输出到/tmp/awk.sh文件中去】
执行结果如下:
--version:显示awk版本信息。
命令:awk --version
-F:指定域分隔符。【用来分隔每条记录中各个域的】
例如:awk -F: print $1 /etc/passwd 【注:打印系统所有的用户;$1代表第一个域】
执行结果如下:
awk基本示例
我们以a.txt文件作为示例文件,a.txt文件内容如下:
打印列或域:
在awk中,对于输入流,输入的每行,叫做一条记录;每一条记录中以分隔符分隔的各个部分叫做域,awk每次载入一条记录进行处理,默认的分隔符为空格。
例如:打印出a.txt文件中姓名和成绩这两列,使用awk进行操作;
命令:awk -F" " print $2,$4 a.txt | column -t 【注:column -t是按比较美观的格式显示输出】
执行结果如下:
输出整行:
$0代表输出整条记录。
例如:输出姓名为wangbin的那行,用awk去实现?
命令:awk -F" " /wangbin/print $0 a.txt 【这条语句先用/pattern/去匹配,匹配到后在输出整行内容】
执行结果如下:
【注:如果没有主体块(即:print $0),则默认是输出记录(行)】
匹配模式输出指定的列(域):
例如:输出姓名为wangbin那行中的第1,2,4列,用awk实现?
命令:awk -F" " /wangbin/print $1,$2,$4 a.txt
执行结果如下:
计算匹配次数并输出:
例如:计算姓名以w开头的行的个数,用awk实现?
命令:
或
awk -F /w/++count END printf "count is: %d\\n",count a.txt
执行结果如下:
输出字符数多于33的行:
例如:打印输出字符串个数多于33的行,用awk实现?
命令:awk -F" " length($0) > 33print $0 a.txt
或者
awk -F" " length($0) > 33 a.txt
执行结果如下:
【注:length函数是awk的内置函数,该函数返回字符串的长度,变量$0表示整行,缺失的主体块会执行默认动作(打印输出);如果一行中的字符数超过33,则length($0) > 33为真,则打印输出,否则不打印】
awk内置变量
Awk提供了一些内置变量,在写脚本或实际运用中起到很重要的作用。
1、标准awk变量:
(1)ARGC
ARGC表示在命令行提供的参数的个数;【注:实际参数个数=ARGC -1,因为第一个参数永远是awk】
例如:awk BEGINprint "arguments = ",ARGC -1 xin ss ll w
执行结果如下:
【注:从上面可以看出,ARGC = 实际参数个数+1】
(2)ARGV
ARGV表示将命令行输出的参数存储为一个数组,ARGV即是这个数组的名称;数组的有效索引从0到ARGC-1;
例如:awk BEGINfor(i=0;i<ARGC;i++) printf "ARGV[%d] = %s\\n",i,ARGV[i] xin ss ll w 【这条命令是循环打印出所有参数】
执行结果如下:
【注:第一个参数永远是awk,索引号为0】
(3)ENVIRON
ENVIRON表示与环境变量相关的关联数组变量;【注:即使用这个内置变量可以查看当前系统环境下的环境变量设置,用法为ENVIRON[“环境变量名”]】
例如:
awk BEGINprint ENVIRON["SHELL"]
awk BEGINprint ENVIRON["PATH"]
执行结果如下:
(4)FILENAME
FILENAME表示当前文件名称;
例如:awk ENDprint FILENAME a.txt
执行结果如下:
【注:开始块中FILENAME未定义,因为BEGIN开始块是在文本处理操作之前执行的,所以FILENAME还没定义,该变量的值为空;一般用于END结束块,打印出当前文件名称】
(5)FS
FS表示输入时的域分隔符,其默认值是空格,可以使用-F参数指定与分隔符;
例如:awk BEGINprint "FS=" FS | cat -A
执行结果如下:
【注:cat -A是显示行结束标识符,linux默认是$;可以看出FS默认是空格】
也可以使用-F参数指定域分隔符;
例如:awk -F: BEGINprint "FS=" FS | cat -A
执行结果如下:
【注:上图显示FS变成了:】
(6)OFS
OFS表示输出时的域分隔符,其默认值也是空格;
例如:打印输出a.txt文件中的第2,3列,并改变与分隔符为”--”,使用awk实现;
命令:
执行结果如下:
(7)NF
NF代表当前输入记录中域的数量;
例如:匹配输出姓名为wangbin的行,并显示这行的域总数;
命令:awk -F" " /wangbin/printf "context: (%s)\\nNF: (%s)\\n",$0,NF a.txt | column -t
执行结果如下:
(8)NR
NR表示当前输入记录数(即行号);
例如:打印输出a.txt文件第2-4行(即1<NR<=4)的内容,用awk实现;
命令:awk -F" " if(NR<=4 && NR>1) print NR,$0 a.txt | column -t
执行结果如下:
(9)FNR
FNR也表示记录数(行号),与NR类似,但是不同在于它是相对于文件而言的,此变量在处理多个文件时有重要的作用,每当从新的文件读入时,FNR都会被重新置为0;
NR与FNR比较:
例如:现在有两个文件a.txt,b.txt,现在要求打印输出并添加行号,分别使用NR和FNR对比效果;
NR显示结果:
【注:如上图执行结果显示,NR是相对于整个输入流而言,行号不断从1开始递增,所以无法通过NR来区分多个文件】
FNR显示结果:
【注:如上图结果显示,FNR是相对于文件而言的,当读入新文件时,FNR会被重新置为0,即当一个文件结束,开始读入第二个文件时,行号重新从1开始递增,所以可以通过FNR来区分多个文件】
(10)RS
RS表示输入记录(行)分隔符【即输入时的记录分隔符】,默认是换行符,可以使用RS指定输入记录分隔符;
例如:echo "1,1--2,2--3,3--4,4--5,5" | awk -F"," BEGINRS="--"print $0
上面的语句:输入文本内容为"1,1--2,2--3,3--4,4--5,5",默认的记录分隔符为换行符,我们使用RS="--"指定记录分隔符为--后,awk主体程序就需要处理五条记录【这五条记录分别为:1,1、2,2、3,3、4,4、5,5】
执行结果如下:
【注:以上就是显示的结果,当然大家可能会发现为什么结尾会多一个空包行呢,print最后默认就会输出一个换行,这个可以不用理会】
(11)ORS
ORS表示输出记录(行)分隔符【即输出时的记录分隔符】,默认是换行符,可以使用ORS指定输出记录分隔符;
例如:将a.txt文件不换行输出,并指定输出记录分隔符为||,用来区分原来的每一条记录,用awk实现;
命令:awk ORS=" || ";print $0 a.txt
执行结果如下:
【结果显示,已将换行符换成了||】
(12)RLENGTH
RLENGTH表示match函数匹配的字符串长度,awk的match函数用于在输入的字符串中搜索指定字符串;
例如:awk BEGINif(match("this is good","good"));print RLENGTH 【表示match函数在输入字符串中匹配good字符串,RLENGTH返回匹配到的good字符串的长度】
执行结果如下:
(13)RSTART
RSTART表示由match函数匹配的字符串的第一个字符的位置【注:是匹配字符串的第一个字符在所有输入的内容中的位置】;
例如:awk BEGINif(match("this is good","good"));print RSTART 【这表示match匹配到的good字符串中的第一个字符”g”在输入内容中”this is good”的位置】
执行结果如下:
- $0
$0表示输入的整个输入记录;
(15)$n
$n表示当前输入记录的第n个域,这些域之间由FS分隔,n的取值为1,2,3......;
awk特定变量(即专有变量)
(1)ARGIND
ARGIND表示当前文件中正在处理的ARGV数组的索引值;
例子:有三个文件分别是junk1、junk2、junk3,每个文件中都有两行;
命令:
执行结果如下:
【注:ARGIND其实就是每个文件的序列号,例如第一个文件是junk1,那么这时ARGIND=1,且会遍历该文件中所有行,有多少行就会输出多少个ARGIND=1(这变量生产中我一次也没用到过)】
ERRNO
ERRNO用于存储当getline重定向失败或者close函数调用失败时的失败信息;
例子:awk BEGINret=getline<"xin.t";if(ret==-1) print "error: ",ERRNO
执行结果如下:
【注:因为xin.t这个文件并不存在,报错,错误信息保存到了ERROR变量中】
IGNORECASE
IGNORECASE表示忽略大小写;
例如:找出a.txt文件中name=wangbin这一行;使用awk这一行
首先不开启,即IGNORECASE=0的情况(区分大小写):
执行结果如下:
开启IGNORECASE,即IGNORECASE=1的情况(忽略大小写):
执行结果如下:
TEXTDOMAIN
TEXTDOMAIN表示awk程序当前文本域,它主要是来寻找程序中字符串的本地翻译,用于程序的国际化;默认值是messages;
例如:
执行结果如下:
awk操作符
算数运算符
加法(+)
例子:awk BEGINa=5;b=3;printf "a + b = %d\\n",a+b
或者
awk BEGINa=5;b=3;print "a + b =",a+b
执行结果如下:
减法(-)
例子:awk BEGINa=5;b=3;printf "a - b = %d\\n",a-b
或者
awk BEGINa=5;b=3;print "a - b =",a-b
执行结果如下:
乘法(*)
例子:awk BEGINa=5;b=3;printf "a * b = %d\\n",a*b
或者
awk BEGINa=5;b=3;print "a * b =",a*b
执行结果如下:
除法(/)【awk除法可以保留精度】
例子:awk BEGINa=5;b=3;printf "a / b = %d\\n",a/b 【结果只保留整数】
【结果保留3位精度】
或者
【默认print输出保留5位精度】
执行结果如下:
(5)模运算符(%)【即取余运算】
例子:awk BEGINa=5;b=3;printf "a % b = %d\\n",a%b
或者
awk BEGINa=5;b=3;print "a % b =",a%b
执行结果如下:
递增运算符之前置递增运算(如++a)
例子:awk BEGINa=5;b=++a;printf "a = %d, b = %d\\n",a,b
执行结果如下:
【注:b=++a表示先执行递增操作,后执行赋值操作,即先执行a=a+1,在执行b=a,所以结果a和b都为6】
递增运算符之后置递增运算(如a++)
例子:awk BEGINa=5;b=a++;printf "a = %d, b = %d\\n",a,b
执行结果如下:
【注:b=a++表示先执行赋值操作,后执行递增操作,即先执行b=a,再执行a=a+1,所以结果a=6,b=5】
递减运算符之前置递减运算(如--a)
例子:awk BEGINa=5;b=--a;printf "a = %d, b = %d\\n",a,b
执行结果如下:
【注:b=--a表示先执行递减操作,后执行赋值操作,即先执行a=a-1,再执行b=a,所以结果a=4,b=4】
递减运算符之后置递减运算(如a--)
例子:awk BEGINa=5;b=a--;printf "a = %d, b = %d\\n",a,b
执行结果如下:
【注:b=a--表示先执行赋值操作,后执行递减操作,即先执行b=a,再执行a=a-1,所以结果a=4,b=5】
赋值运算符
简单赋值(=)
例子:awk BEGINname = "zx";printf "name = %s\\n",name
执行结果如下:
将awk脚本写在文件里:一种高效的awk循环循环方式