Consolida o prefixo repetido

2

Eu tenho um arquivo de log como:

Bug123:c:SomeComment
Bug222:c:SomeOtherComment
Bug123:c:SecondComment

Eu preciso produzir:

Bug123
    SomeComment
    SecondComment
Bug222
    SomeComment

Usando o bash, parece que não consigo pensar em uma maneira de realizar isso de uma maneira simples. Alguma idéia?

    
por Leo Ufimtsev 20.06.2017 / 01:28

3 respostas

4
$ awk 'BEGIN {FS=":"} {comments[$1][NR]=$3} END {for (bug in comments) { print bug; for (comment in comments[bug]) { print "    ",comments[bug][comment] } } }  ' /path/to/input
Bug123
     SomeComment
     SecondComment
Bug222
     SomeOtherComment

Isso funciona configurando um array multidimensional enquanto ele lê o arquivo de entrada e, em seguida, percorre os dados resultantes na ordem em que os "bugs" são vistos. Com alguns pequenos ajustes, isso poderia ser modificado para classificar a matriz de nível externo.

    
por 20.06.2017 / 01:35
2

Aqui está uma maneira divertida de fazer isso em vi (ou, na verdade, em ex se você omitir os dois pontos principais de cada comando):

:%!awk -F: '{a[$1];print} END {for (i in a) {print i}}'
:v/:/m0
:%!sort -st: -k1,1
:%s/^.*:/\t/

Explicação:

O comando Awk imprime todas as linhas como estão e copia uma lista de todos os primeiros campos exclusivos no final do arquivo.

O v command m oves para a linha 0 (o início do arquivo) todas as linhas que não possuem dois-pontos. (Em outras palavras, a lista dos primeiros campos é a saída de awk .)

O comando sort faz uma classificação s table, preservando a ordem das linhas além de organizá-las de acordo com o primeiro campo. (Nós já movemos os campos "header" para o início do arquivo.)

Em seguida, o comando s ubstitute transforma o prefixo de cada linha sem cabeçalho em uma guia.

Resultado da entrada fornecida:

Bug123
    SomeComment
    SecondComment
Bug222
    SomeOtherComment

Explicações adicionais:

: (colon) é o que você digita em vi para iniciar um comando ex -style.

% é um intervalo de endereços em ex . Significa "aplicar a seguinte ação / comando a todas as linhas no buffer (arquivo)".

Quando usado com um endereço, ! inicia um "filtro" em ex : as linhas especificadas pelo endereço são alimentadas como entrada para o comando externo especificado e são substituídas no buffer pela saída desse comando .

-F: define o separador de campo Awk.

{} (chaves) são usados no Awk para envolver comandos a serem executados. Como não há nenhum endereço Awk precedendo as chaves (dentro das aspas simples), as ações nas chaves são aplicadas a cada linha de entrada.

a[$1] cria um elemento de matriz usando o primeiro campo da linha atual ( $1 ) como o índice. Como ele não diz = "whatever" , o elemento da matriz não tem valor , mas isso não importa; nós apenas queremos que o array contenha esse elemento.

; termina o comando Awk.

print é o comando Awk para imprimir a linha atual (por padrão) ou quaisquer argumentos que forem passados (como no último print i ).

END marca o bloco de ações (em chaves) para ser executado depois que toda entrada (para Awk) for processada.

O loop for imprime todos os índices da matriz chamada a . Quais são os primeiros campos desduplicados do arquivo de log, em nenhuma ordem específica.

Tanto para o comando Awk.

O comando v é um comando ex , que é o oposto do comando g lobal. g realiza uma ação em todas as linhas correspondentes a um determinado padrão. v executa a ação especificada em todas as linhas que NÃO correspondem ao padrão fornecido.

/ inicia e termina o padrão. Que é apenas : neste caso.

m significa "mover". Por isso, :v/:/m0 in vi move todas as linhas que não contêm dois pontos para o topo do arquivo.

O resto dos comandos deve ser bem claro. :)

    
por 20.06.2017 / 02:50
2

perl one-liner

perl -MList::Util=uniq -F: -lane '
        push @keys, $F[0];
        push @{ $comment{$F[0]} }, $F[2];
    } END { 
        for $key (uniq @keys) {
            print $key;
            print "    $_" for @{$comment{$key}};
        }
' file
    
por 20.06.2017 / 16:53