awk - Agrupa e soma valores da coluna

2

Eu tenho o comando para listar o processo do sistema pelo uso da memória:

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

Qual lista de uma tabela como

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

Eu gostaria de obter o compartilhamento total de memória por programas em vez de por processo dos mesmos programas. Então eu poderia obter uma saída como

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

Eu pensei em usar awk , que eu não sei muito. Acabou com algo como:

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

Mas não funcionou.

Como posso corrigir isso?

    
por Junaid 11.11.2014 / 08:58

2 respostas

6

processes[$0] += $1; usa a linha inteira como chave em sua matriz associativa, o que não é exclusivo. Você deve usar $1 , que é o nome do comando como chave.

Tente:

$ 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];
    }
  }
'

Se você quiser classificar a saída pelo segundo campo, tente:

$ 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";
    }
  }
'
    
por 11.11.2014 / 09:07
1

cuonglm answer resolve seu erro, para obter os valores na ordem crescente (conforme solicitado em seu comentário), canalize a saída por sort -n -k 2 (classifique como números ( -n , no segundo campo ( -k 2 ), depois de alterar o comando print para gerar os floats como no seu exemplo:

$ 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/'

Saída (usando sua tabela como entrada em vez de fazer ps no meu sistema):

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

Alternativamente, você pode canalizar a saída através deste programa python (se você quiser ordenação decrescente (como no seu exemplo), altere o reverse=False para 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])
    
por 11.11.2014 / 09:26

Tags