40

いくつかのドメインを含む domainというファイルがあります。例えば:

google.com
facebook.com
...
yahoo.com

また、いくつかのサイトの URL と番号を含むsiteという別のファイルがあります。例えば:

image.google.com   10
map.google.com     8
...
photo.facebook.com  22
game.facebook.com   15
..

次に、各ドメインの URL 番号を数えます。例: google.comには10+8があります。そこで、次のような awk スクリプトを作成しました。

BEGIN{
  while(getline dom < "./domain" > 0) {
    domain[dom]=0;
  }
  for(dom in domain) {
    while(getline < "./site" > 0) {
      if($1 ~/$dom$)   #if $1 end with $dom {
        domain[dom]+=$2;
      }
    }
  }
}

しかし、コードif($1 ~/$dom$)は思い通りに実行されません。正規表現の変数 $dom を文字どおりに説明したからです。したがって、最初の質問は次のとおりです。

$dom正規表現で変数を使用する方法はありますか?

それから、私はスクリプトを書くのが初めてなので

私が抱えている問題を解決するためのより良い方法はありますか?

4

5 に答える 5

21

まず、変数はそうではありdomません$dom--変数$に格納されている列番号の値を抽出する演算子として考えますdom

第二に、 awk はその間にあるものを補間しません//-それはそこにある単なる文字列です。

match()2 番目の引数が正規表現として扱われる文字列である関数が必要です。

if (match($1, dom "$")) {...}

次のようなソリューションをコーディングします。

awk '
  FNR == NR {domain[$1] = 0; next}
  {
    for (dom in domain) {
      if (match($1, dom "$")) {
        domain[dom] += $2
        break
      }
    }
  }
  END {for (dom in domain) {print dom, domain[dom]}}
' domain site 
于 2012-07-18T04:30:52.937 に答える
1

awkスクリプトを使用する1つの方法:

BEGIN {
    FS = "[. ]"
    OFS = "."
}

FNR == NR {
    domain[$1] = $0
    next
}

FNR < NR {
    if ($2 in domain) {
        for ( i = 2; i < NF; i++ ) {
            if ($i != "") {
                line = (line ? line OFS : "") $i
            }
        }
        total[line] += $NF
        line = ""
    }
}

END {
    for (i in total) {
        printf "%s\t%s\n", i, total[i]
    }
}

次のように実行します:

awk -f script.awk domain.txt site.txt

結果:

facebook.com    37
google.com  18
于 2012-07-18T05:53:54.270 に答える
1

siteのエントリごとに 1 回ではなく、ファイルを 1 回読み取りたいのは明らかですdomain。ただし、それを修正するのは簡単です。

同様に、(フィールド..などawk以外の) 内の変数には..というプレフィックスは付けられません。特に、変数によって識別されるフィールド番号です(通常、ドメイン文字列は他の番号に変換されないため、これになります)。$0$9$$domdom0

ファイルから読み取ったデータからドメインを取得する方法を見つける必要があると思いsiteます。bbc.co.uk国別ドメインのサイトや GTLD 内のサイト (google.comなど)を処理する必要があるかどうかはわかりません。国のドメインを扱っていないと仮定すると、これを使用できます。

BEGIN {
    while (getline dom < "./domain" > 0) domain[dom] = 0
    FS = "[ .]+"
    while (getline  < "./site" > 0)
    {
        topdom = $(NF-2) "." $(NF-1)
        domain[topdom] += $NF          
    }
    for (dom in domain) print dom "  " domain[dom]
}

2 番目のwhileループにはNFフィールドがあります。$NFにはカウントが含まれ、$1..$(NF-1)ドメインのコンポーネントが含まれます。そのためtopdom、最上位のドメイン名が含まれることになり、最初のループで初期化された配列にインデックスを付けるために使用されます。

問題のデータ (ドットの行を除く) が与えられると、出力は次のようになります。

yahoo.com  0
facebook.com  37
google.com  18
于 2012-07-18T11:29:36.903 に答える