awk - グループ化基準と列値の合計

awk - グループ化基準と列値の合計

メモリ使用量別にシステムプロセスを一覧表示するコマンドがあります。

ps -A --sort -rss -o comm,pmem

同様の表がリストされています。

COMMAND         %MEM
firefox         28.2
chrome           5.4
compiz           4.8
atom             2.5
chrome           2.3
Xorg             2.3
skype            2.2
chrome           2.0
chrome           1.9
atom             1.9
nautilus         1.8
hud-service      1.5
evince           1.3

同じプログラムのプロセスではなく、プログラムごとの合計メモリ共有を取得したいと思います。だから私はこの結果を得ることができます

COMMAND         %MEM
firefox         28.2
chrome          11.6
compiz           4.8
atom             4.4
Xorg             2.3
skype            2.2
nautilus         1.8
hud-service      1.5
evince           1.3

を使ってみようかと思いましたがawk、よく理解できません。次のように終わりました。

ps -A --sort -rss -o comm,pmem | awk -F "\t" '
{processes[$0] += $1;}
{End
for(i in processes) {
  print i,"\t",processes[i];
}
}'

しかし、それはうまくいきませんでした。

この問題をどのように解決できますか?

答え1

processes[$0] += $1;行全体を一意でない連想配列のキーとして使用します。$1つまり、コマンド名をキーとして使用する必要があります。

努力する:

$ ps -A --sort -rss -o comm,pmem | awk '
  NR == 1 { print; next }
  { a[$1] += $2 }
  END {
    for (i in a) {
      printf "%-15s\t%s\n", i, a[i];
    }
  }
'

2番目のフィールドに基づいて出力をソートするには、次のようにします。

$ ps -A --sort -rss -o comm,pmem | awk '
  NR == 1 { print; next }
  { a[$1] += $2 }
  END {
    for (i in a) {
      printf "%-15s\t%s\n", i, a[i] | "sort -rnk2";
    }
  }
'

答え2

cuonglmの答えは、タイプミスを修正して値を取得します。増加あなたのコメントで要求されたように出力をパイピングして(sort -n -k 22番目のフィールド()で数字()でソート)、例のようにprintステートメントを浮動小数点として出力するように変更した後:-n-k 2

$ ps -A --sort -rss -o comm,pmem | awk '
  NR == 1 { print; next }
  { a[$1] += $2 }
  END {
    for (i in a) {
      printf "%-15s\t%.1f\n", i, a[i];
    }
  }
' | sed 's/%MEM/-1MEM/' | sort -n -k 2 | sed 's/-1MEM/%MEM/'

出力(テーブルを入力として使用し、psシステムで実行しない):

COMMAND         %MEM
evince          1.3
hud-service     1.5
nautilus        1.8
skype           2.2
Xorg            2.3
atom            4.4
compiz          4.8
chrome          11.6
firefox         28.2

または、このPythonプログラムを使用して出力をパイプ処理することもできます(例のように降順が必要な場合は次のようreverse=Falseに変更します)reverse=True

#! /usr/bin/env python
# coding: utf-8

import sys
import operator

d = {}
for line in sys.stdin:
    try:
        name, val = line.split()
        val = float(val)
        d.setdefault(name, [0.0])[0] += val
    except ValueError:
        print line,

for x in sorted(d.items(), reverse=False, key=operator.itemgetter(1)):
    print "{:16s}{:>4}".format(x[0], x[1][0])

関連情報