awk的学习和使用(三)

上一篇 / 下一篇  2009-08-17 17:50:03 / 个人分类:Linux

先看一篇文本,名为testfile,共6个字段:site、engine、url、num1、num2、num3

"Boharu Sweet Days"     Google http://www.acpit.com/~rental1/atlinkb/linkdisp.cgi?ID=mari215&KEY1=j01&RT=s1&SORT1=1    8       8  8
"Aoharu Sweet Days"     Google http://www.acpit.com/~rental1/atlinkb/linkdisp.cgi?ID=mari215&KEY1=j01&RT=s1&SORT1=1    8       8  8
"Aoharu Sweet Days"     Google http://www.acpit.com/~rental1/atlinkb/linkdisp.cgi?ID=mari215&KEY1=j01&RT=s1&SORT1=1    8       8  8
"Aoharu weet Days"      Bing   http://www.acpit.com/~rental1/atlinkb/linkdisp.cgi?ID=mari215&KEY1=j01&RT=s1&SORT1=1    8       8  0

A.找出site、engine、url均相同的记录,将这些相同记录的num1,mum2、num3相加;

B.找到后三个值中为0的记录,将其赋值为NULL;

解题思路:

第一步:排序

第二部:求和

第三部:判断num为0的记录,做字符串替换

1.sort即可将其排序。注:sort testfile表示将文件中的每一行进行全排序,先从第一个字段排序,一直到最后一个字段;字段由第一个字母排序,直到最后一个字母;sort的分隔符指定参数为-t,由于本例是由第一个字段往后进行全排序,因此不需要额外指定分隔符;

2.比较前三个字段的值并求和,用awk。由于awk默认的分隔符为tab或者空格均视为分隔符,因此根据本文的特殊性(第一个字段中包含空格),需要单独指定分隔符为tab,打印第一个字段看看:

awk -F"\t" '{print $1}' 结果正确。

3.字符串替换.

3.1由于需要检查的字符串本身都是一个单独的字段(num1、num2、num3),因此可以使用awk字段判定:

if($4=="0")$4="NULL";

3.2另外可以使用awk的内部函数gsub来替换字符串:

gsub(/0/,"NULL");

这样子的结果会将每行中所有0都替换为NULL,实际我们只要求将tab后紧跟着的0替换为NULL,linux下tab可以用\<\>表示:

gsub(/\<0\>/,"NULL"); 表示将tab后面的0替换为NULL(这个解释非常奇怪,但是结果是对的。。有待考察)

3.3字符串替换功能,一般会使用比较简洁的sed 's/source-charactor/dest-charactor/'。其中的字符匹配支持正则表达式。

sed 's/\t0/\tNULL'

4.最后:

    处理问题A的awk文件:testA.awk

BEGIN{FS="\t"}
{if(NR==1)
{
        site=$1;engin=$2;url=$3;n1=$4;n2=$5;n3=$6;
}
else if(site==$1&&engin==$2&&url==$3)
{
        n1+=$4;n2+=$5;n3+=$6;
}
else
{
        print(site"\t"engin"\t"url"\t"n1"\t"n2"\t"n3);
        site=$1;engin=$2;url=$3;n1=$4;n2=$5;n3=$6;}
}
END{print(site"\t"engin"\t"url"\t"n1"\t"n2"\t"n3)}

    处理问题B的awk文件:testB.awk

BEGIN{FS="\t"}
{
        if($4=="0")$4="NULL";
        if($5=="0")$5="NULL";
        if($6=="0")$6="NULL";
        print($1"\t"$2"\t"$3"\t"$4"\t"$5"\t"$6);
}

合并:

sort testfile | awk -f testA.awk | awk -f testB.awk > out

 


TAG:

 

评分:0

我来说两句

Open Toolbar