一、概念
awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
二、使用格式
1.命令行方式
awk [-F field-separator] 'commands' input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。
2.shell脚本方式
将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
相当于shell脚本首行的:#!/bin/sh
可以换成:#!/bin/awk
3.将所有的awk命令插入一个单独文件,然后调用:
awk -f awk-script-file input-file(s)
其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。
三、变量
变量分为内置变量和自定义变量,但只要是变量都是用的选项-v
。
先选常用的内置变量说明下,然后说下自定义的变量。
1、内置变量:
FS
:输入字段分隔符,默认为空白字符,这个想当于-F
选项。分隔符可以是多个,用[]括起来表示,如:-v FS="[,./-:;]"
OFS
:输出字段分隔符,默认为空白字符,分隔符可以是多个,同上RS
:输入记录(所认为的行)分隔符,指定输入时的换行符,原换行符仍有效,分隔符可以是多个,同上ORS
:输出记录(所认为的行)分隔符,输出时用指定符号代替换行符,分隔符可以是多个,同上NF
:字段数量NR
:记录数(所认为的行)FNR
:各文件分别计数, 记录数(行号)FILENAME
:当前文件名ARGC
:命令行参数的个数ARGV
:数组,保存的是命令行所给定的各参数
2、自定义变量(区分字符大小写):
在'{...}'前,需要用-v var=value:
awk -v var=value '{...}'
在program 中直接定义:awk '{var=vlue}'
下面针对每个变量都举个例子:
awk -v FS=':' '{print $1,FS,$3}’ /etc/passwd
awk –F: '{print $1,$3,$7}’ /etc/passwd
awk -v FS=‘:’ -v OFS=‘:’ '{print $1,$3,$7}’ /etc/passwd
awk -v RS=' ' ‘{print }’ /etc/passwd
awk -v RS="[[:space:]/=]" '{print }' /etc/fstab |sort
awk -v RS=' ' -v ORS='###'‘{print }’ /etc/passwd
awk -F: ‘{print NF}’ /etc/fstab, 引用内置变量不用$
awk -F: '{print $(NF-1)}' /etc/passwd
awk '{print NR}' /etc/fstab ; awk 'END{print NR}' /etc/fstab
awk '{print FNR}' /etc/fstab /etc/inittab
awk '{print FNR}' /etc/fstab /etc/inittab
awk '{print FILENAME}’ /etc/fstab
awk '{print ARGC}’ /etc/fstab /etc/inittab
awk ‘BEGIN {print ARGC}’ /etc/fstab /etc/inittab
awk ‘BEGIN {print ARGV[0]}’ /etc/fstab /etc/inittab
awk ‘BEGIN {print ARGV[1]}’ /etc/fstab /etc/inittab
awk -v test='hello gawk' '{print test}' /etc/fstab
awk -v test='hello gawk' 'BEGIN{print test}'
awk 'BEGIN{test="hello,gawk";print test}'
awk –F:‘{sex=“male”;print $1,sex,age;age=18}’ /etc/passwd
awk -F: '{sex="male";age=18;print $1,sex,age}' /etc/passwd
echo "{print script,\$1,\$2}" > awkscript
awk -F: -f awkscript script=“awk” /etc/passwd
四、awk的print和printf
print和printf都是打印输出的,不过两者用法和显示上有些不同而已。
print 格式:
print item1,item2, ...
printf格式:printf “FORMAT ”,item1,item2, ...
要点:
1.逗号为分隔符时,显示的是空格;
2.分隔符分隔的字段(域)标记称为域标识,用$0,$1,$2,...,$n表示,其中$0 为所有域,$1就是表示第一个字段(域),以此类推;
3.输出的各item可以字符串,也可以是数值,当前记录的字段,变量或awk 的表达式等;
4.如果省略了item ,相当于print $0
5.对于printf来说,必须指定FORMAT,即必须指出后面每个itemsN的输出格式,且还不会自动换行,需要显式则指明换行控制符"\n"
printf的格式符和修饰符:
%c
:显示字符的ASCII码%d, %i
:显示十进制整数%e, %E
:显示科学计数法数值%f
:显示为浮点数%g, %G
:以科学计数法或浮点形式显示数值%s
:显示字符串%u
:无符号整数%%
:显示%自身#[.#]
:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f-
:左对齐(默认右对齐);%-15s,就是以左对齐方式显示15个字符长度+
:显示数值的正负符号 %+d
这里也举个示例:
awk '{print "hello,awk"}'
awk –F: '{print}' /etc/passwd
awk –F: ‘{print “wang”}’ /etc/passwd
awk –F: ‘{print $1}’ /etc/passwd
awk –F: ‘{print $0}’ /etc/passwd
awk –F: ‘{print $1”\t”$3}’ /etc/passwd
tail –3 /etc/fstab |awk ‘{print $2,$4}’
awk -F: ‘{printf "%s",$1}’ /etc/passwd
awk -F: ‘{printf "%s\n",$1}’ /etc/passwd
awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd
awk -F: ‘{printf "Username: %s\n",$1}’ /etc/passwd
awk -F: ‘{printf “Username: %s,UID:%d\n",$1,$3}’ /etc/passwd
awk -F: ‘{printf "Username: %15s,UID:%d\n",$1,$3}’ /etc/passwd
awk -F: ‘{printf "Username: %-15s,UID:%d\n",$1,$3}’ /etc/passwd
lsmod
awk -v FS=" " 'BEGIN{printf "%s %26s %10s\n","Module","Size","Used by"}{printf "%-20s %13d %5s %s\n",$1,$2,$3,$4}' /proc/modules
五、awk的break、continue和next
break 和continue,用于条件判断循环语句,next是用于awk自身循环的语句。
break[n]
:当第n次循环到来后,结束整个循环,n=0就是指本次循环continue[n]
:满足条件后,直接进行第n次循环,本次循环不在进行,n=0也就是提前结束本次循环而直接进入下一轮next
:提前结束对本行的处理动作而直接进入下一行处理
示例:
awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}‘
awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}‘
awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
六、AWK的函数
awk的函数有许多,除了系统自带的内建函数还有就是用户自定义的函数,这里挑选几个常用的函数。
rand()
:返回0 和1 之间一个随机数srand()
:生成随机数种子int()
:取整数length([s])
:返回指定字符串的长度sub(r,s,[t])
:对t
字符串进行搜索,r
表示的模式匹配的内容,并将第一个匹配的内容替换为s
gsub(r,s,[t])
:对t
字符串进行搜索,r
表示的模式匹配的内容,并全部替换为s
所表示的内容split(s,array,[r])
:以r
为分隔符,切割字符串s
,并将切割后的结果保存至array
所表示的数组中,第一个索引值为1, 第二个索引值为2,…也就是说awk
的数组下标是从1开始编号的。substr(s,i,[n])
:从s
所表示的字符串中取子串,取法:从i
表示的位置开始,取n
个字符。systime()
:取当前系统时间,结果形式为时间戳。system()
:调用shell中的命令。空格是awk中的字符串连接符,如果system 中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用"" 引用 起来。
自定义函数,格式为
function fname ( arg1,arg2 , ... ) {
statements
return expr
}
自定义函数中fname为函数名,arg1...为函数的参数,statements是动作语言,return expr为由statements的结果从而决定最终函数所显示的内容。
示例:
cat fun.awk
function max(v1,v2) {
v1>v2?var=v1:var=v2
return var
}
BEGIN{a=3;b=2;print max(a,b)}
awk –f fun.awk
七、awk的脚本
awk的脚本就是将awk程序写成脚本形式,来直接调用或直接执行。例如上面写自定义函数的样子也算是脚本。
格式1:
BEGIN{} pattern{} END{}
格式2:
\#!/bin/awk -f
\#add 'x' right
BEGIN{} pattern{} END{}
格式1假设为f1.awk文件,格式2假设为f2.awk文件,那么用法是:
awk [-v var=value] f1.awk [file]
f2.awk [-v var=value] [var1=value1] [file]
对于awk [-v var=value] f1.awk [file]
来说,很好理解,就是把处理阶段放到一个文件而已,真正展开后,也就是普通的awk语句。
对于f2.awk [-v var=value] [var1=value1] [file]
来说, [-v var=value]
是在BEGIN之前设置的变量值,[var1=value1]
是在BEGIN过程之后进行的,也就是说直到首行输入完成后,这个变量才可用,这就想awk脚本黄总传递参数了。
示例:
cat f1.awk
{if($3>=1000)print $1,$3}
awk -F: -f f1.awk /etc/passwd
cat f2.awk
#!/bin/awk –f
#this is a awk script
{if($3>=1000)print $1,$3}
#chmod +x f2.awk
f2.awk –F: /etc/passwd
cat test.awk
#!/bin/awk –f
{if($3 >=min && $3<=max)print $1,$3}
#chmod +x test.awk
test.awk -F: min=100 max=200 /etc/passwd
八、awk常见小题
1、统计输出结果的最后一列之和:
result | awk -F'\t' -v sum=0 '{sum += $NF} END{print sum}'
2、统计文件 t1.log 中最后一列中大于 5 的那些域的和,并将其输出:
awk -v sum=0 '{if($NF>5) sum+=$NF} END{print sum}'
3、求和
cat data|awk '{sum+=$1} END {print "Sum = ", sum}'
4、求平均
cat data|awk '{sum+=$1} END {print "Average = ", sum/NR}'
5、求最大值
cat data|awk 'BEGIN {max = 0} {if ($1>max) max=$1 fi} END {print "Max=", max}'
4、求最小值(min的初始值设置一个超大数即可)
awk 'BEGIN {min = 1999999} {if ($1<min) min=$1 fi} END {print "Min=", min}'
九、更多