análise de texto da coluna

3
2018-05-24 23:57:30 1.1.1.1 8.8.4.4
2018-05-24 23:57:32 2.2.2.2 8.8.4.4
2018-05-24 23:58:12 8.8.8.8 8.8.4.4
2018-05-24 23:58:23 8.8.8.8 8.8.4.4
2018-05-24 23:59:40 8.8.8.8 8.8.4.4
2018-05-24 23:59:51 8.8.8.8 8.8.4.4

Como eu tenho o arquivo de log no formato acima. Agora preciso analisá-lo e a saída deve ficar como abaixo (Mostrando apenas Primeira e Última linha comparando a terceira e a quarta coluna se os dados da linha forem repetidos.

2018-05-24 23:57:30 1.1.1.1 8.8.4.4
2018-05-24 23:57:32 2.2.2.2 8.8.4.4
2018-05-24 23:58:12 8.8.8.8 8.8.4.4
2018-05-24 23:59:51 8.8.8.8 8.8.4.4
    
por BDN 25.05.2018 / 18:02

6 respostas

4

com awk :

awk '!first[$3, $4]{ first[$3, $4]= $0 } { last[$3, $4]= $0 }
    END{ for (x in last) print first[x] (last[x] != first[x]? ORS last[x]:"") }' infile
2018-05-24 23:58:12 8.8.8.8 8.8.4.4
2018-05-24 23:59:51 8.8.8.8 8.8.4.4
2018-05-24 23:57:30 1.1.1.1 8.8.4.4
2018-05-24 23:57:32 2.2.2.2 8.8.4.4

A matriz first associada mantém a primeira linha ocorrida com a combinação de teclas da coluna 3 e da coluna 4, mas a matriz last mantém a linha mais recente sempre com as mesmas chaves.

Após todas as linhas terem sido lidas, os valores em first array são as linhas que ocorreram no primeiro (com diferentes colunas # 3, # 4) e os valores em last são as linhas que ocorreram no último.

Em seguida, no END , imprima os valores salvos em first array e, em seguida, em last .  Esse (last[x] != first[x]? ORS last[x]:"") é usado para impedir a duplicação da linha quando essa é a única linha exclusiva sem combinação repetida de coluna3 e 4.

    
por 25.05.2018 / 18:17
6

Perl para o resgate:

perl -ane '
    if ($F[2] ne $c3 || $F[3] ne $c4) {
        $printed or print $previous;
        $printed = print;
    } else {
        $printed = 0;
    }
    ($c3, $c4, $previous) = (@F[2, 3], $_);
    END { print $previous unless $printed }
' -- input.file
  • -n lê a entrada linha por linha e executa o código para cada linha.
  • -a divide cada linha de entrada no espaço em branco no array @F.
  • $ c3 e $ c4 são usados para manter os valores anteriores das colunas 3 e 4, os valores reais são armazenados em $ F [2] e $ F [3] (matrizes são indexadas de 0).
  • $ previous armazena a linha anterior, caso precisássemos imprimi-la.
  • $ printed apenas impede a impressão da última linha duas vezes (o que aconteceria caso suas colunas 3 e 4 fossem diferentes da linha anterior).
por 25.05.2018 / 18:14
0

Você também pode usar apenas linhas exclusivas comparando as colunas 3,4 e, em seguida, acrescentar a última linha neste caso. Mas isso pode resultar em uma última linha duplicada se todas as outras linhas tiverem colunas 3 e 4 diferentes.

Em seguida, basta adicionar outro canal ao uniq para remover, se necessário.

{uniq <your_file> -f2; tail -n1 <your_file>; } | cat | uniq

-f aqui pula os primeiros 2 campos delimitados por espaço.

    
por 25.05.2018 / 22:31
0
 perl -lane '
   *x = sub { print for splice @A; } if $. == 1;
   x() if $. > 1 and $F[2] ne $c3 || $F[3] ne $c4;
   ($c3, $c4, $A[!!@A]) = (@F[2,3], $_);
   x() if eof;
 '    include.txt

§ Como funciona.

    °  Array @A holds only 2 elements max at any time. The beginning and end lines for the range.

   °  subroutine &x displays the array @A and after displaying empties it as well.

  °  display the previous range provided we are not at the first line and either of the previous columns don't match with the current.

  °   update the previous columns and array. 
    
por 26.05.2018 / 12:47
0

Primeira variante

paste -d'\n' <(uniq -f2 input.txt) <(tac input.txt | uniq -f2 | tac) | uniq

Segunda variante

awk '
$3$4 == prev {
    buf = $0 ORS
}
$3$4 != prev {
    print buf $0
    prev = $3$4
    buf = ""
}
END {
    printf("%s", buf)
}' input.txt

Teste

Entrada (complicada para testes)

2018-05-24 23:57:30 1.1.1.1 8.8.4.4
2018-05-24 23:57:32 2.2.2.2 8.8.4.4
2018-05-24 23:58:12 8.8.8.8 8.8.4.4
2018-05-24 23:58:23 8.8.8.8 8.8.4.4
2018-05-24 23:59:40 8.8.8.8 8.8.4.4
2018-05-24 23:59:51 8.8.8.8 8.8.4.4
2018-05-25 00:18:12 8.8.1.8 8.8.4.4
2018-05-25 00:18:23 8.8.1.8 8.8.4.4
2018-05-25 00:19:40 8.8.1.8 8.8.4.4
2018-05-25 00:19:51 8.8.1.8 8.8.4.4
2018-05-25 00:39:51 8.8.2.8 8.8.4.4
2018-05-25 00:49:52 8.8.2.8 8.8.4.4
2018-05-25 00:59:51 8.8.2.8 8.8.4.4

Saída (ambas as variantes)

2018-05-24 23:57:30 1.1.1.1 8.8.4.4
2018-05-24 23:57:32 2.2.2.2 8.8.4.4
2018-05-24 23:58:12 8.8.8.8 8.8.4.4
2018-05-24 23:59:51 8.8.8.8 8.8.4.4
2018-05-25 00:18:12 8.8.1.8 8.8.4.4
2018-05-25 00:19:51 8.8.1.8 8.8.4.4
2018-05-25 00:39:51 8.8.2.8 8.8.4.4
2018-05-25 00:59:51 8.8.2.8 8.8.4.4
    
por 26.05.2018 / 14:50
0
 perl -lane '
   *x = sub { print for splice @A; } if $. == 1;
   x() if $. > 1 and $F[2] ne $c3 || $F[3] ne $c4;
   ($c3, $c4, $A[!!@A]) = (@F[2,3], $_);
   x() if eof;
 '    include.txt

§ Como funciona.

    °  Array @A holds only 2 elements max at any time. The beginning and end lines for the range.

   °  subroutine &x displays the array @A and after displaying empties it as well.

  °  display the previous range provided we are not at the first line and either of the previous columns don't match with the current.

  °   update the previous columns and array.

¶ Outro método é elaborado usando o editor sed.

 #! /bin/sh
  # declare regex assist variables
   b='[:space:]'
   s="[$b]"         # \s
   S="[^$b]"       # \S

   #      \S+                \s+
   F="$S$S*"   sp="$s$s*"
   F_s="$F$sp"      #  \S+\s+

   # composition of a line 
   L="$F_s$F_s\($F\)$sp\($F\)"

   #  matching next line
   M=".*$s$sp"

   #    2 lines when they match with 3,4 fields
   L2="$L\(\n$M\)\{1\}"

   # 3 lines when they match in fields 3,4
   L3="$L\(\n$M\)\{2\}"

  #### code 
  sed -e '
       #  bring on board next line for interrogation 
        N

         #   2 lines fields 3,4 donot match 
          #  display the first line... redo code with remaining 
         '"/^$L2\$/"'!{
                  P;D
           }

            #  3 lines with first two match but third not match in fields 3,4
           :a;h;N
           '"/^$L3\$/"'!{
                 x;p;g
                 s/.*\(\n\)//;D
              }

              s/\n.*\(\n\)//;ba
      '   include.txt 
    
por 27.05.2018 / 05:21

Tags