awk deseja totalizar por hora e variável

1

Eu posso executar isso e funciona bem - note: o campo $ 1 é um campo com data / hora carimbada ...

gawk -F ":" "{ print $1 }" /cygdrive/c/counting/ourlog | sort | uniq -c | sort -r
  57339 2014-03-21 09
  54290 2014-03-21 08
  54036 2014-03-21 10
  53254 2014-03-21 11
  52777 2014-03-21 12
  50785 2014-03-21 07
  49729 2014-03-21 16
  44459 2014-03-21 15
  43932 2014-03-21 13
  43335 2014-03-21 06
  40952 2014-03-21 14
  40864 2014-03-21 17

Agora, o que eu quero fazer é suprimir as primeiras 10 linhas (elas são comentários anteriores com um #) - e isso pode variar. Então, queremos procurar as primeiras linhas xx que começam com #.

Alteramos o script para:

gawk -F ":" "{ print $1 }" /cygdrive/c/counting/ourlog | sort | uniq -c | sort -r | gawk -v MyID="$id" '/#/{n++}; END {print n+0}' | gawk "NR> MyID "

mas isso não funciona. Se fizermos mais algumas alterações, vemos o resultado desejado:

gawk -F ":" "{ print $1 }" /cygdrive/c/counting/ourlog | gawk "NR>10" | sort | uniq -c | sort -r

Eu sei que posso digitar fisicamente 10 para pular as primeiras 10 ou 20 linhas. No entanto, quero que seja um valor calculado.

    
por Leptonator 01.04.2014 / 07:53

3 respostas

4

Aqui está o código awk para pular somente os comentários iniciais e, em seguida, print $1 nas linhas restantes:

gawk -F: -v c=1 '/^[^#]/ {c=0} c==0 { print $1 }' ourlog

Antes do início do programa, a variável c é configurada para 1. Assim que uma linha sem comentário for encontrada, c será definido como zero e permanecerá assim até o final da execução. Quando c==0 , a instrução print é executada.

Se você quiser apenas eliminar todos os comentários, o código é muito mais simples:

gawk -F: '/^[^#]/ { print $1 }' ourlog

O item acima verifica cada linha em relação à expressão regular ^[^#] , que corresponde apenas se o primeiro caractere não for # . Se coincide com (linha não é um comentário), então a instrução print é executada.

    
por 01.04.2014 / 08:35
0

Desde que meu Post original foi editado para questões gramaticais ... Eu tenho que colocar isso como uma nova "resposta" ...

Aqui está outra maneira de abordar isso e eu não pensei nisso até esta manhã ..

sed "/#/d" "/cygdrive/c/!chkout/ourlog" | gawk -F ":" "{print $1}"  | sort | uniq -c | sort -r
    
por 01.04.2014 / 15:44
0

Não sei exatamente o que você deseja fazer porque não mostra a entrada real, apenas a saída desejada e vários bits de código usados em vários estágios. No entanto, acho que o seguinte fará o que você quer (certifique-se de definir -F: na linha de comando. Se não, tentei descrever cada parte para dar uma idéia de como modificá-la.

!/^#/ {                                      # do the following on all rows that don't begin 
                                             # with '#'

    a[$1]++                                  # store column 1 as the key in an array and
                                             # increment the value for each occurrence
}

END {                                        # do the following after reading the entire file

    PROCINFO["sorted_in"] = "@ind_num_desc"; # set array traversal as numeric index descending
                                             # (requires gawk >= 4.0, otherwise, additional code
                                             # will be needed)

    for (i in a) {                           # loop through the array setting i as the index of
                                             # the current entry

        print a[i], i;                       # print the value (row count) and the index (the
                                             # row)
    }
}    

Eu não acho que você precise passar mais uma variável, porque parece que foi usado apenas para identificar quantas linhas de comentário iniciais pular, mas se você quiser fazer isso, você quase o teve no seu exemplo, mas cada vez que você invoca gawk , é uma instância nova. Você passou a variável para a instância antes da que a usou. Então, no seu exemplo acima, você precisaria mudar para:

gawk -F ":" "{ print $1 }" /cygdrive/c/counting/ourlog \
    | sort | uniq -c | sort -r                         \
    | gawk '/#/{n++}; END {print n+0}'                 \
    | gawk -v MyID="$id" "NR> MyID "

Mas tudo isso pode ser combinado. As duas últimas linhas apenas contam as linhas com # e, eu acho, tentam passar esse valor para outra instância, mas você acabou de imprimi-lo para STDOUT, então não tenho certeza de como isso funcionaria. Então apenas modifique a primeira linha para que o awk pule essas linhas:

gawk -F: '!/^#/ { print $1 }' /cygdrive/c/counting/ourlog \
    | sort | uniq -c | sort -r

Se é isso que você quer, e você quer evitar todos os canais, o código acima funcionará.

    
por 12.04.2014 / 15:52