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");

}

}

}

}

相关推荐