一个awk脚本bug我无法解决

时间:2012-07-18 16:03:53

标签: awk

我有两个档案。 domain.txt 包含一些域名

facebook.com
google.com
yahoo.com

site.txt 包含域名下的部分网站及其网址号。

music.google.com  2
image.google.com  3
music.facebook.com  8
image.facebook.com  4
map.yahoo.com   4
new.yahoo.com   7

我要选择网站,其网址数量大于其域名的平均网址数量。例如, google.com 的平均网址数为(2 + 3)/2=2.5 ,因此 image.google.com 将被选中。

我写了这样的awk脚本:

BEGIN {
        #read all domains into memory
        while(getline dom < "./domain.txt" > 0){
                domain[dom]=0;
        }

        #count URLs number and sites number under each domain
        for (dom in domain){
                sitenumber=0;

                close("./site.txt")
                while(getline < "./site.txt" >0){
                        if(match($1,"."dom"$")){
                                domain[dom]+=$2;
                                sitenumber++;
                                printf("%s\n",$0) >> "./sitesunderdomain";
                        } 
                }

                avgsitenumber = domain[dom]/sitenumber;
                system("cat ./sitesunderdomain") #test output

                close("./sitesunderdomain")
                while(getline < "./sitesunderdomain" >0){ #loop A
                        print "why1" #test output
                        if($2>=avgsitenumber){
                                print "why2"  #testoutput
                                print $0,avgsitenumber>>"./result"
                        }
                }
                system("> ./sitesunderdomain")
        }#for
}

然后我在bash中运行awk脚本,得到输出:

music.facebook.com  8
image.facebook.com 4
why1
why2
why1
music.google.com   2
image.google.com  3
map.yahoo.com  4
news.yahoo.com  7

./ result

music.facebook.com  8  6

但正如我所料,输出应为

music.facebook.com  8
image.facebook.com 4
why1
why2
why1
music.google.com   2
image.google.com  3
why1
why2
why1
map.yahoo.com  4
news.yahoo.com  7
why1
why2
why1

./ result 应为:

music.facebook.com  8  6
image.google.com  3  2.5
news.yahoo.com  7  5.5

似乎在loop A位置,getline0 google.com yahoo.com <时返回dom / strong>即可。 的为什么吗

2 个答案:

答案 0 :(得分:2)

你的代码很乱。这不是使用awk的方式。 Awk会自动逐行打开并读取您的文件,这不是使用getline的工作。这仅适用于特殊情况。

首先

close("./site.txt")
while(getline < "./site-test" >0){

./site-test?您的文件是test.txt。它在我的测试中死了。

第二:当您可以直接从RAM重用数据时,无需创建文件,例如数组。

第三个​​:我根本不喜欢你的代码,但要修复它,请在用./sitesunderdomain读取getline临时文件和删除system("> ./sitesunderdomain")之前删除## NOT here. ##close("./sitesunderdomain") while(getline < "./sitesunderdomain" >0){ #loop A print "why1" #test output if($2>=avgsitenumber){ print "why2" #testoutput print $0,avgsitenumber>>"./result" } } ## Better here between the read and the write. close("./sitesunderdomain") system("> ./sitesunderdomain") 临时文件{1}},如:

awk -f myscript.awk domain.txt site.txt

现在运行如下脚本:

cat result

并检查输出:

music.facebook.com  8 6
image.google.com  3 2.5
new.yahoo.com   7 5.5

以下结果:

{{1}}

答案 1 :(得分:1)

我无法理解您的脚本。没有必要手动打开这样的文件; awk自己负责。如果您的代码可以修复,我不是那样做的。

以下是我提出的内容:

#!/usr/bin/awk -f

{
  domain=$1; sub(/^[a-z]*\./, "", domain);
  mean[domain]=(mean[domain]*count[domain]+$2)/++count[domain];
  score[$1]=$2;
}

END {
  printf("%7s\t%6s\t%s\n", "score", "mean", "domain");
  for (hostname in score) {
    domain=hostname; sub(/^[a-z]*\./, "", domain);
    if (score[hostname] > mean[domain]) {
      printf("%6d\t%6.2f\t%s\n", score[hostname], mean[domain], hostname);
    }
  }
}

当我针对您的数据运行它时,我得到以下结果:

  score   mean  domain
     3    2.50  image.google.com
     8    6.00  music.facebook.com
     7    5.50  new.yahoo.com

这是你期望的输出吗?