2行ブロックの一意のインスタンスを計算する[閉じる]

2行ブロックの一意のインスタンスを計算する[閉じる]

与えられた入力:

144.252.36.69
afrloop=32235330165603
144.252.36.69
afrloop=32235330165603
144.252.36.69
afrloop=32235330165603
222.252.36.69
afrloop=31135330165603
222.252.36.69
afrloop=31135330165603
222.252.36.69
afrloop=31135330165603
222.252.36.69
afrloop=31135330165603

どのように出力できますか?

144.252.36.69
afrloop=32235330165603 3 times
222.252.36.69
afrloop=31135330165603 4 times

答え1

paste - - < file | sort | uniq -c

答え2

awkカスタム出力形式が必要な場合はこれが解決策です

NR%2==1 {ip=$0; next}
NR%2==0 {a[ip"\n"$0]++}
END {
    for(i in a)
        printf "%s %d times\n", i, a[i]
}

スクリプトは次のように実行できます。

awk -f main.awk file

説明する

  • まず、奇数モジュロ2が1に等しいため、奇数行を一致させるために使用しますNR%2==1。行がこの条件と一致すると、行全体が名前付き$0変数に保存されますip。これを使用してnext追加の処理をスキップし、次の繰り返しに直接移動できます。

  • 第二に、偶数行を一致させるために使用しますNR%2==0。行が一致すると、ip"\n"$0配列にインデックスを作成し、aその特定のインデックスの数値を増やします。たとえば、同等の拡張は次のとおりです。

    a["144.252.36.69 afrloop=32235330165603"] += 1
    

    \n簡単にするために、この例では新しい行を無視しています。

  • 最後にEND、各行を処理した後、ループを使用してfor配列内の各要素値a(この場合は各固有インデックスの数)を印刷します。

面白いベンチマーク

  • テストファイルの生成(100万レコード)

    awk '
        BEGIN{for(i=1;i<10000000;i++)
        printf "%d\nafrLoop=%d\n", int(rand()*100), int(rand()*10)}
    ' > test
    
    $ head test
    23
    afrLoop=2
    84
    afrLoop=1
    58
    
  • @n.caillouペーストソリューション

    $ time paste - - < test | sort | uniq -c > /dev/null
    real    0m11.250s
    user    0m11.352s
    sys     0m0.272s
    
  • 奇妙なソリューション

    $ time awk -f main.awk test > /dev/null
    real    0m5.673s
    user    0m5.636s
    sys     0m0.036s
    

関連情報