AWK攻略----网摘
前言
一、AWK简介
AWK名字来源于三位创造者Aho、Weinberger和Kernighan统称。
AWK擅长处理文本数据。
二、AWK的调用方式
awk[-Ffs][-vvar=value][program|-fprogfile...][file...]
1、命令行方式
例如:
awk'{print$1}'file
ps-ef|grepprogram|awk'{print$2}'
2、文件方式
例如:
awk-fprogfilefile
3、文件解释器方式
AWK脚本文件开头需要注明调用方式,典型写法为:
#!/bin/awk-f
注意-f后面有空格。
脚本文件需要有执行权限,如果没有需要使用chmod+xprogfile赋权。
例如:
progfilefile
三、AWK参数
-F指定域分隔符,例如:-F"|",即以|作为域分隔符,默认分隔符为一个或多个空格或TAB,即"[[:space:]][[:space:]]*"。
-v定义变量,从shell给awk传递变量,如-vDATE=$DATE,即将shell中$DATE变量值传递给awk变量DATE。
-f指定脚本文件,例如-fprogfile。
四、AWK内置变量
FS域分隔符
NF域个数
NR行数
FNR同上
FILENAME处理的文件名,当输入为管道时,FILENAME为空。
RS行分隔符
OFS输出域分隔符
ORS输出行分隔符
OFMT数字输出格式
CONVFMT数字内部转换格式
SUBSEP多维数组索引分隔符
ARGC输入参数个数
ARGV输入参数数组
ENVIRON环境变量数组
RSTARTmatch()函数正则匹配到字符串开始位置
RLENGTHmatch()函数正则匹配到字符串的长度
五、AWK内置函数
blength[([s])]计算字符串长度(byte为单位)
length[([s])]计算字符串长度(character为单位)
rand()生成随机数
srand([expr])设置rand()seed
int(x)字符串转换为整型
substr(s,m[,n])取子字符串
index(s,t)在字符串s中定位t字符串首次出现的位置
match(s,ere)在字符串s中匹配正则ere,match修改RSTART、RLENGTH变量。
split(s,a[,fs])将字符串分割到数组中
sub(ere,repl[,in])字符串替换
gsub同上
sprintf(fmt,expr,...)拼字符串
system(cmd)在shell中执行cmd。
toupper(s)字符串转换为大写
tolower(s)字符串转换为小写
六、AWK流程控制
if(expression)statement[elsestatement]
while(expression)statement
for(expression;expression;expression)statement
for(varinarray)statement
dostatementwhile(expression)
break
continue
{[statement...]}
expression#commonlyvar=expression
print[expression-list][>expression]
printfformat[,expression-list][>expression]
return[expression]
next#skipremainingpatternsonthisinputline.
deletearray[expression]#deleteanarrayelement.
exit[expression]#exitimmediately;statusisexpression.
七、AWK简单应用范例
AWK脚本分为三部分BEGIN段,处理段,END段。其中BEGIN段在第一行读取之前执行,END段在最后一行处理后执行。
1、内容过滤,同"greptagfile"。
#前两个语句为正则匹配
awk'/tag/{print}'file
awk'{if($0~/tag/)print}'file
awk'{if(index($0,"tag")>0)print}'file
2、取特定列,同"cut–f1–f3–f5file"。
#输出文件第1、3、5列
awk'{print$1,$3,$5}'file
3、对文件内容进行剔重,类似"sort-ufile",但未排序。
#如果当前行未存在于recHASH表中,则记录此行数据,并输出
awk'{if(!($0inrec)){rec[$0]=1;print$0;}}'file
AWK中数组有两种用法普通数组和HASH数组,此处为HASH数组。
4、仅输出数据
#输出100行数据
awk‘BEGIN{for(i=0;i<100;i++)printf("thisis%d\n",i);}’
可见,如果脚本中只有BEGIN段,可以没有输入。
5、统计数据
#对第一列和第二列数据进行汇总,最终输出
awk‘{a+=$1;b+=$2}END{printf("a=%d\n,b=%d\n",a,b);}’file
八、AWK高级应用范例
1、分组功能,类似Groupby功能
#使用第一列作为分组列,第二列为聚合列,即selectcol1,sum(col2)fromfilegroupbycol1
awk‘{tot[$1]+=$2}END{for(iintot)printf("%s%d\n",i,tot[i]);}’file
#比上个例子增加一个类似having的用法
awk‘{tot[$1]+=$2}END{for(iintot)if(tot[i]>10)printf("%s%d\n",i,tot[i]);}’file
#使用第一列作为分组列,第二列、第三列为聚合列
awk‘{tot1[$1]+=$2;tot2[$1]+=$3;}END{for(iintot1)printf("%s%d%d\n",i,tot1[i],tot2[i]);}’file
#多维数组例子,可将多个字段作为分组列,AWK使用一维数组模拟多维数组,使用\034作为分隔符
awk‘{tot1[$1,$2]+=$3;tot2[$1,$2]+=$4;}END{for(iintot1)printf("%s%d%d\n",i,tot1[i],tot2[i]);}’file
2、文件操作
#将两个文件根据filename1的第一列和filename2的第二列进行关联
BEGIN{
#读取filename1文件内容
while((getline<"filename1")!=NULL)
{
rel[$1]=1;
rec1[$1]=$2;
}
while((getline<"filename2")!=NULL)
{
rel[$2]=1;
rec2[$2]=$3;
}
for(iinrel)
{
printf("%s%s%s\n",i,rec1[i],rec2[i]);
}
}
#将文件按照字段进行拆分
{
print$0>>"split/"substr($1,1,7);
}
3、从SHELL向AWK传递变量
awk-vAWK_DATE=$DATE'BEGIN{printAWK_DATE}'
4、在AWK内部读取shell命令输出
#读取ls命令输出,在AWK中打印输出
BEGIN{
while("ls"|getline)
{
print$0;
}
}
#读取date输出
BEGIN{
"date"|getline;
print$0;
"date+%Y"|getlinev_year;
printv_year;
}
5、将AWK输出通过管道传递给SHELL命令
#将打印信息输出给sort进行排序
BEGIN{
for(i=0;i<100;i++)
{
printf("%03d\n",100-i)|"sort";
}
}
6、正则表达式简单例子
#演示正则表达式的使用方法
BEGIN{
str1="[email protected]";
str2="[email protected]";
str3="&^%[email protected]";
str4="[email protected]";
match(str1,"[a-zA-Z][a-zA-Z0-9.]*@[a-zA-Z0-9][a-zA-Z0-9.]*.[a-zA-Z]*[a-zA-Z]");
if(RSTART>0)
printf("%s\n",substr(str1,RSTART,RLENGTH));
else
printf("[%s]notmatch\n",str1);
match(str2,"[a-zA-Z][a-zA-Z0-9.]*@[a-zA-Z0-9][a-zA-Z0-9.]*.[a-zA-Z]*[a-zA-Z]");
if(RSTART>0)
printf("%s\n",substr(str2,RSTART,RLENGTH));
else
printf("[%s]notmatch\n",str2);
match(str3,"[a-zA-Z][a-zA-Z0-9.]*@[a-zA-Z0-9][a-zA-Z0-9.]*.[a-zA-Z]*[a-zA-Z]");
if(RSTART>0)
printf("%s\n",substr(str3,RSTART,RLENGTH));
else
printf("[%s]notmatch\n",str3);
match(str4,"[a-zA-Z][a-zA-Z0-9.]*@[a-zA-Z0-9][a-zA-Z0-9.]*.[a-zA-Z]*[a-zA-Z]");
if(RSTART>0)
printf("%s\n",substr(str4,RSTART,RLENGTH));
else
printf("[%s]notmatch\n",str4);
}
7、自定义函数
functionmy_plus(a,b)
{
returna+b;
}
BEGIN{
printf("%d\n",my_plus(123,321));
}
九、一些应用范例
1、验证话单正确性的一个脚本
/^vc/{
#取话单中各个变量
call_type=substr($0,3,2);
call_duration=int(substr($0,95,6));
roam_type=substr($0,210,1);
fee_type=substr($0,211,1);
dial_type=substr($0,212,3);
chat_type=substr($0,215,3);
cfee=int(substr($0,218,9));
lfee=int(substr($0,236,9));
#如果为国际漫游,不分析,跳过
if(roam_type>4)
{
next;
}
if(call_type=="01")
{
if(substr(dial_type,1,1)!="0")
{
if(lfee>0)
{
printf("%s:LFEE_01\n",$0);
}
next;
}
if(roam_type!="0")
{
if(fee_type=="0"||fee_type=="2"||fee_type=="3")
{
if(lfee>0)
{
printf("%s:LFEE_ERR02\n",$0)
}
}
else
{
if(cfee>0)
{
printf("%s:CFEE_ERR01\n",$0);
}
}
}
else
{
if(fee_type!="0")
{
if(cfee>0)
{
printf("%s:CFEE_ERR02\n",$0);
}
}
}
}
if(call_type=="02")
{
if(lfee>0)
{
printf("%s:LFEE_ERR03\n",$0);
}
}
}
2、一个模拟求取批价标批费率计划的例子
functionmy_match(str,pat)
{
#fordebug
#printf("str==>|%s|,pat==>|%s|\n",str,pat);
if(pat=="*")
return1;
n=split(pat,arr,",");
for(z=1;z<=n;z++)
{
gsub("\?","[a-zA-Z0-9]",arr[z]);
#fordebug
#printf("str==|%s|,arr==>|%s|\n",str,arr[z]);
match(str,arr[z]);
if(RSTART>0)
{
return1;
}
}
return0;
}
BEGIN{
dial_cnt=0;
while((getline<"dial.lst")!=NULL)
{
dial[dial_cnt]=$1;
dial_cnt++;
}
chat_cnt=0;
while((getline<"chat.lst")!=NULL)
{
chat[chat_cnt]=$1;
chat_cnt++;
}
cfg_cnt=0;
while((getline<"plan.lst")!=NULL)
{
cfg_dial[cfg_cnt]=$1;
cfg_chat[cfg_cnt]=$2;
cfg_item[cfg_cnt]=$3;
cfg_plan[cfg_cnt]=$4;
cfg_cnt++;
}
for(d=0;d<dial_cnt;d++)
{
for(c=0;c<chat_cnt;c++)
{
printf("%s%s|",dial[d],chat[c]);
out_cnt=0;
for(i=0;i<cfg_cnt;i++)
{
#fordebug
#printf("\n<%d,%d,%d>testmatch==>|<%s,%s>;<%s,%s>|\n",d,c,i,dial[d],cfg_dial[i],chat[c],cfg_chat[i]);
if(my_match(dial[d],cfg_dial[i])==1&&my_match(chat[c],cfg_chat[i])==1)
{
if(out_cnt==0)
{
printf("%s%s%s%s\n",cfg_item[i],cfg_plan[i],cfg_dial[i],cfg_chat[i]);
}
else
{
printf("%s%s|%s%s%s%s\n",dial[d],chat[c],cfg_item[i],cfg_plan[i],cfg_dial[i],cfg_chat[i]);
}
out_cnt++;
}
}
if(out_cnt==0)
{
printf("NULL\n");
}
}
}
}