AWKは最初の3つの値を探します。

AWKは最初の3つの値を探します。

4つの列を持つ大容量データファイルがあり、4番目の列は行の合計値です。最初の3列に入力された最初の3つの値が見つかるはずです。次のAWKは出力を生成しますが、データファイルの4番目の列で重複した合計を見つけると停止します。誰かがこのAWKにカウンタループを追加して正しい出力を生成する方法を案内できますか?

BEGIN { FS="," }

{
  site=$1
  region=$2
  town=$3
  totcnt=$4+0

  key=site","region","town

  if (totcnt >=max) {
    max=totcnt
    mytot[key]=max
  }
}

END { for (i in mytot) {print i "," mytot[i]} }

非常にありがとう

答え1

次のPerlスクリプトは、配列ハッシュ(またはHoA)と呼ばれるデータ構造を使用します。ハッシュ(%sites)には、最初の3つのフィールド(サイト、地域、都市)から派生したキーがあり、ハッシュの各要素は、その特定のキーのすべての合計を含む配列です。

HoA を作成するには、各行を読み取って先行または末尾のスペースを削除し、空行を無視します。また、コメント(文字で始まるすべて#)を無視します。なぜなら、実行しやすく、テキストデータファイルのデータに注釈を付けることができると便利です。

スクリプトは入力ファイル全体を読み取り、各キーに属する配列を逆順に並べ替え、各キーの最初の3つの値のみを含む要約行を印刷します。

#!/usr/bin/perl

my %sites=();

while(<>) {
  chomp;
  s/#.*//;        # strip comments #
  s/^\s*|\s*$//g; # strip leading and trailing spaces
  next if (/^$/); # skip blank lines

  my($site,$region,$town,$total) = split /,/;
  my $key = "$site,$region,$town";

  push @{ $sites{$key} }, $total;
}

foreach my $k (sort keys %sites) {
  @{ $sites{$k} } = reverse sort @{ $sites{$k} };
  print $k . ": " . join(", ",@{ $sites{$k}}[0..2] ), "\n";
};

出力例:

$ ./jon.pl input.txt
site1,North,Bristol: 996776, 9776, 6776
site2,South,Guildford: 99392, 392, 2392
site2,South,London: 99381, 381, 2381
site3,Central,Birmingham: 992628, 5628, 2628
site3,Wales,Cardiff: 99834, 9834, 834
site3,Wales,Swansea: 991796, 3796, 21796
site5,South,Guildford: 99338, 338, 2338
site5,South,London: 99266, 3266, 266
site5,South,Windsor: 99359, 359, 2359
site5,West,Bristol: 997700, 9700, 7700

input.txtあなたが提供し、何度もコピーしたサンプルデータと、コピーで編集された合計が含まれます。

出力はより細かく修正するか、各合計に対して1行を印刷するように簡単に変更できます(ヒント、Join()の代わりに配列要素[0..2]を繰り返します)。


ところで、それははいでこのようなものを実装することは可能ですが、で行う方がはるかにawk簡単ですperl

答え2

3つの最大値を維持するには、2つの配列を使用できます。各配列には3つの要素が含まれています。 1つは実際の値のもので、もう1つは関連キーのものです。これらは秘密にしておく必要があります。

BEGIN { FS = "," }

{
    key = sprintf("%s,%s,%s", $1, $2, $3)
    value = $4

    for (i = 1; i <= 3; ++i)
        if (values[i] == "" || values[i] < value) {
            tmp = values[i]
            values[i] = value
            value = tmp

            tmp = keys[i]
            keys[i] = key
            key = tmp
        } else break
}

END {
    for (i = 1; i <= 3; ++i)
        printf("%s,%d\n", keys[i], values[i])
}

これは2つの配列とvaluesを使用しますkeys。読み取られた各値(value = $4)の値を確認してください。各値についてvaluesどれよりも大きいか確認してください。もしそうなら、value「現在の値」()をvalues[i]それ配列の値「バブル」です。アレイはkeysアレイと同期したままですvalues

テスト:

$ cat file
A1,B2,C3,35
A4,B5,C6,607
A7,B8,C9,159
A10,B11,C12,100
A13,B14,C15,116
A16,B17,C18,688
A19,B20,C21,346
A22,B23,C24,277
A25,B26,C27,931
A28,B29,C30,552
A31,B32,C33,605
A34,B35,C36,109
$ awk -f script.awk file
A25,B26,C27,931
A16,B17,C18,688
A4,B5,C6,607

関連情報