Classificar linha com base no valor de uma coluna

Classificar linha com base no valor de uma coluna

Eu tenho que classificar um despejo de thread que se parece com isso:

$ jstack -l 5213 | grep cpu 

"Reference Handler" #2 daemon prio=10 os_prio=0 cpu=2.21ms elapsed=478.03s tid=0x00000000013bb800 nid=0x1465 waiting on condition  [0x00007f386cc0c000]
"Finalizer" #3 daemon prio=8 os_prio=0 cpu=1.30ms elapsed=478.03s tid=0x00000000013c6000 nid=0x1466 in Object.wait()  [0x00007f386cb0b000]
"Signal Dispatcher" #4 daemon prio=9 os_prio=0 cpu=0.31ms elapsed=478.03s tid=0x00000000013db000 nid=0x1467 runnable  [0x0000000000000000]
"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 cpu=3042.89ms elapsed=478.02s tid=0x00000000013dd800 nid=0x1468 waiting on condition  [0x0000000000000000]
"C1 CompilerThread0" #8 daemon prio=9 os_prio=0 cpu=1840.51ms elapsed=478.02s tid=0x00000000013e0000 nid=0x1469 waiting on condition  [0x0000000000000000]

O dump é muito grande, então gostaria de classificá-lo pela coluna "cpu" (crescente ou decrescente). Parece que o comando sort aceita o parâmetro "k" para indicar a coluna a ser usada como critério de classificação. "cpu" é a 5ª coluna, então tentei com:

$ jstack -l 5213 | grep cpu | sort -k 5
"ServerService Thread Pool -- 1" #26 prio=5 os_prio=0 cpu=10.86ms elapsed=753.24s tid=0x0000000002b68800 nid=0x1482 waiting on condition  [0x00007f385c33b000]
"Transaction Expired Entry Monitor" #131 daemon prio=5 os_prio=0 cpu=0.48ms elapsed=751.66s tid=0x00000000082ed000 nid=0x14eb in Object.wait()  [0x00007f3853826000]
"Transaction Reaper Worker 0" #133 daemon prio=5 os_prio=0 cpu=0.13ms elapsed=751.63s tid=0x00000000084d9000 nid=0x14ee in Object.wait()  [0x00007f3853523000]

Vejo que o pedido mudou, mas não segue os critérios esperados ("cpu"). Alguma ideia se um texto como "cpu=value" pode ser usado como critério de classificação ou precisa ser combinado com outros comandos? Obrigado

Responder1

Existe um "padrão" de design que pode ser adotado ao classificar linhas inteiras em um subconjunto de entrada, que por si só não pode ser recuperado diretamente. Nesses casos, fazer isso em um pipeline de vários estágios como abaixo seria melhor do que escrever um comando completo em Awk ou Perl

Uma maneira de fazer isso é usar o Awk para extrair a mssubstring, converter em numérico e imprimir a linha inteira e o valor em milissegundos e classificar com base no último e cortá-lo depois.

Canalize a saída do seu comando para o seguinte

awk 'match($0, /cpu=[[:digit:].]+/){print substr($0, RSTART+4, RLENGTH-1)+0, $0}' | 
sort -n -k1,1 | 
cut -d' ' -f2-

Para ordem decrescente de tempos, adicione o -rsinalizador asort

Responder2

Se você usar =como separador de campo, o valor da CPU estará no 4º campo. Você pode fazer

jstack -l 5213 | grep cpu | sort -t '=' -g -k4,4

com -gpara classificação "numérico geral".

Com dados fornecidos, a saída é

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 cpu=0.31ms elapsed=478.03s tid=0x00000000013db000 nid=0x1467 runnable  [0x0000000000000000]
"Finalizer" #3 daemon prio=8 os_prio=0 cpu=1.30ms elapsed=478.03s tid=0x00000000013c6000 nid=0x1466 in Object.wait()  [0x00007f386cb0b000]
"Reference Handler" #2 daemon prio=10 os_prio=0 cpu=2.21ms elapsed=478.03s tid=0x00000000013bb800 nid=0x1465 waiting on condition  [0x00007f386cc0c000]
"C1 CompilerThread0" #8 daemon prio=9 os_prio=0 cpu=1840.51ms elapsed=478.02s tid=0x00000000013e0000 nid=0x1469 waiting on condition  [0x0000000000000000]
"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 cpu=3042.89ms elapsed=478.02s tid=0x00000000013dd800 nid=0x1468 waiting on condition  [0x0000000000000000]

Isso pressupõe que o sinal de igual não apareça na string citada, portanto não é tão estável quanto a resposta de @Inian.

informação relacionada