awk的内部变量的个数不多,在这里介绍的时候就不按照字母顺序排列了,而是按相关性分类说明。
ARGC
ARGC表示命令行上除了选项-F,-v,-f等选项及其所对应的参数之外的所有参数的个数。如果将“awk程序”直接写在命令行上,那么ARGC是不会把“awk程序”计算在内的。
ARGV
ARGV是一个数据,用来记录命令行上的参数的名称。 执行下列命令:
[root@myfreelinux pub]# awk ‘BEGIN{printf(“ARGC=%d/n”,ARGC);for(a in ARGV)printf(“ARGV[%d]=%s/n”,a,ARGV[a]);}’ inte integer
ARGC=3
ARGV[0]=awk
ARGV[1]=inte
ARGV[2]=integer
需要注意当ARGC = 3 时,命令列上只指定了2 个文件。
awk的参数-F/t 表示以tab 为栏位分隔字符FS(field seporator);-v a=8 是用以初始化程序中的变量。
FILENAME
FILENAME用来表示目前正在处理的文件名。
FS域分隔字符
$0 表示目前awk所读入的数据行的内容,$1,$2…示所读入的数据行经过FS指定分割符分割后的第一域,第二域…的记过。
说明:当awk读入一行数据行”A123 8:15″ 时,会先以$0 记录,即$0 = “A123 8:15″,如果程序中进一步使用了$1,$2…或 NF等内部变量时,awk才会自动分割 $0,以便取得各域的数据。 切割后各个域的数据会分別用$1,$2, $3…等存储。
awk默认的(default)域分隔字符(FS)为空白字符(空格及tab)。以上例来说,如果没有改变FS的值,那么分割后:第一个域($1)=”A123″,第二个域($2)=”8:15″。也可以使用正则表达式来定义FS,比如FS=/[ /t:]+/,表示0或多个空格、tab、:分别或他们三个任意组合成的字符串作为分割符,awk每次需要分割数据行时,就会参考目前FS的值。 那么这定FS后,$0 = “A123 8:15″,将被分割为,第一个域($1) = “A123″,第二个域($2) = “8″,第三个域($3) = “15″。
NR (number record)
NR表示awk 开始执行该程序后所读取的数据行数。
FNR (file number record)
FNR 与NR功用类似;不同的是awk在处理多个数据文件的时候,每打开一个新的文件,FNR便从0重新累计,而NR是一直累加,看个列子更直观些,见下列:
[root@myfreelinux pub]# cat inte
123
324
[root@myfreelinux pub]# cat integer
222 111
333 111
444 111
[root@myfreelinux pub]# awk ‘BEGIN{print NR,FNR,$0}’ inte integer
0 0
[root@myfreelinux pub]# awk ‘{print NR,FNR,$0}’ inte integer
1 1 123
2 2 324
3 1 222 111
4 2 333 111
5 3
6 4 444 111
NF (number field)
NF表示当前行被域分隔符分割成的域的个数。awk 每读入一笔数据后,在程序中用NF记录该行数据包含的域的个数。在下一行数据被读入之前,NF不会改变。但如果使用$0来记录数据,例如:使用getline,此时NF将代表新的$0上数据的域的个数。
OFS (output file separate)
OFS输出域分隔字符。默认是” “(一个空白)
ORS (output Record separate)
ORS输出数据行分隔字符。默认值是”/n”(换行符)。
OFMT(output format)
OFMT数值数据的输出格式。默认值”%.6g”(若须要时最多印出6位小数)。
当使用print指令一次打印出多项数据时,例如:print $1,$2,输出时,awk会自动在$1与$2之间补上一个域分隔符的值(OFS 之值);每次使用print输出后,awk会自动补上h行分隔符的值(ORS 之值)。使用print 输出数值数据时,awk将采用 OFMT 之值为输出格式。例如:
[root@myfreelinux pub]# awk ‘BEGIN{print 2/3;OFS=”:”;OFMT=”%.2g”;print 2/3,1;}’
0.666667
0.67:1
程序中通过改变OFS和OFMT的值,改变了指令print的输出格式。
RS
RS( Record Separator) :awk从文件上读取数据时,将根据RS的定义把数据切割成许多Records,awk一次只读入一个Record进行处理。RS 的默认值是换行符”/n”,所以一般awk一次仅读入一行数据。有时一个Record含括了几行数据(Multi-line Record),这情況下不能再以”/n” 来分隔相邻的Records,可改用空白行来分隔,即令RS = “”,表示以空白行来分隔相邻的Records。
RSTART
RSTART与使用字串函数match( )有关的变量,是匹配的字符的开始的位置。
RLENGTH
RLENGTH与使用字串函数match( )有关的变量,RLENGTH是匹配的字符串的长度。当使用match() 函数后,awk会将match() 执行的结果以RSTART和RLENGTH记录。看下面的例子:
[root@myfreelinux pub]# awk ‘BEGIN{match(“banana”,”an”);print RSTART,RLENGTH}’
2 2
[root@myfreelinux pub]# awk ‘BEGIN{match(“banana”,/(an)+/);print RSTART,RLENGTH}’
2 4
[root@myfreelinux pub]# awk ‘BEGIN{match(“banana”,/(na)+/);print RSTART,RLENGTH;}’
3 4
SUBSEP
SUBSEP(Subscript Separator) 数组下标的分隔字符,默认值为”/034″实际上,awk中的数组只接受字串当它的下标,比如: Arr["John"]。但awk中仍然可使用数字当数组的下标,甚至可使用多维的数组(Multi-dimenisional Array),比 如:Arr[2,20]。事实上,awk在接受Arr[2,20]之前,就已先把其下标转换成字串”2/03420″,之后便以Arr["2/03420"] 代替Arr[2,20]。可参考下例:
[root@myfreelinux pub]# awk ‘BEGIN{arr[2,20]=13;print arr[2,20];print arr["2/03420"];idx=2 SUBSEP 20;print arr[idx];}’
13
13
13
再看下面这个例子,统计每门课有几个学生选修,用课程名称作为数组的下标:
[root@myfreelinux pub]# cat kecheng.dat
zhangsan math english chinese
lisi computer chinese english
wangwu dianzi chinese math
zhaoliu huanjing english chinese
[root@myfreelinux pub]# cat kecheng.awk
#!/bin/awk -f
{
for(i=2;i<=NF;i++)
array[$i]++;
}
END{
for(one_array in array)
print one_array,array[one_array];
}
[root@myfreelinux pub]# awk -f kecheng.awk kecheng.dat
computer 1
english 3
dianzi 1
chinese 4
math 2
huanjing 1