awkはファイルから必要なデータを取得し、列ごとに印刷します。

awkはファイルから必要なデータを取得し、列ごとに印刷します。

以下のテキストファイルがあります。

mark     10 20 30
lawrence 40 22 60
mark     11 12 13
mike     15 16 17
lawrence 21 22 23
mike     31 32 33
mike     41 42 47

これを処理し、次の条件を満たす出力を生成したいと思います。

  • 識別名ごとに1行(最初の列)したがって、上記の例では、「Mark」、「Lawrence」、および「Mike」のそれぞれに1つずつ3つの出力ラインが必要です。
  • 出力は入力と表面的に似ているようです。
    • 4つの列。
    • 出力の最初の列は名前(入力の最初の列)です。
    • 2番目、3番目、4番目の列は整数です。
  • 2 番目の列は、名前が最初の列に表示される回数です。
  • 3番目の列は最初の列に名前が表示される回数で、3番目の列に入力した値は20です。
  • 4番目の列は最初の列に名前が表示される回数で、3番目の列に入力した値は22です。

予想出力:

mark     2  1  0
mike     3  0  0
lawrence 2  0  2

私は書いた

... | awk '{ c[$1]++ } END { for (name in c) print name, c[name] }'

私のコードは出力のみです。

mark     2 
mike     3 
lawrence 2 

答え1

awk '
    {name[$1]++}      #Counts how many times each name appear
    $3==20{x20[$1]++} #Counts how many times 20 appears in third column
    $3==22{x22[$1]++} #Counts how many times 22 appears in third column
    END{
        for (i in name){
            printf "%s %d %d %d\n",i,name[i],x20[i],x22[i]
        }
    }
' file

出力:

mike 3 0 0
lawrence 2 0 2
mark 2 1 0

答え2

同様の概念@quasimodoからの返信ただし、1つの場所では3の代わりに値20と値が使用され、22値は配列名にハードコードされません。

awk '
    { namesCnt[$1]++; pairsCnt[$1,$3]++ }
    END {
        for (name in namesCnt) {
            print name, namesCnt[name], pairsCnt[name,20]+0, pairsCnt[name,22]+0
        }
    }
' file

答え3

質問のように出力を列に並べ替えるには、他の答えの1つを選択します(クワジモドまたは エドモートン)にパイプしてcolumn -t

関連情報