Necessidade de filtrar os dados com base em duas colunas com muitos para um relacionamento usando o awk

1

Eu tenho um arquivo grande com colunas de 50s e 100K de linhas delimitadas por |. Agora, $ 2 (col 2) tem vários tipos de $ 1 (col 1), o que significa que col 2 será repetido. Então eu classifiquei o arquivo. Eu preciso agora extrair / filtrar o arquivo de resultado com base na condição abaixo: $ 1 é a coluna 1 $ 2 é a coluna 2

há de um para muitos envios de relacionamento entre $ 2 e $ 1

condition 1 : when $2 has both type of $1 (value of $1 for $2 is more than 8000 as well as less than 8000) then select the complete row where $1 < 8000 for the given $2(column 2)

condition 2: if $2 has only $1 >= 8000 then select the complete row where $1 is the smallest for the given $2(column 2) E.g: source file In the below example we have 3 types of $2 (1234,123 & 456) Now 1234 has 3 types of value in column 1 ($1) means greater as well as less than 8000. So we have selected the complete row for those having $1<8000.

Para 123 e 465, temos o valor da coluna 1 maior que 8000 ($ 1 > 80000), por isso, selecionamos a linha que é mais recente (com base no maior valor da coluna 8).

Exemplo de arquivo

  4000|1234||||||23
    5000|1234||||||40
    9000|1234||||||25
    10000|123|||||||21
    9000|123|||||||22
    22000|456|||||||27
    15000|456|||||||29

arquivo de resultado teria:

4000|1234||||||23
5000|1234||||||40

9000|123|||||||22

15000|456|||||||29

Por favor, conselhos. Agradecemos antecipadamente.

    
por api1411 29.05.2016 / 07:33

1 resposta

3

tente (sendo seu arquivo)

sort -n -t\| -k2 -k1 < u |
awk -F\| '$1 < 8000 { a[$2]++ ; print } 
          $1 >= 8000 { if ( !a[$2] && ( !e[$2] || e[$2]<$8 ))  {u[$2]=$0;e[$2]=$8;} ; } 
          END { for ( i in u ) print u[i] ;}'

4000|1234||||||23
5000|1234||||||40
15000|456||||||29
9000|123||||||22

onde

  • -t\| e -F\| instruem o sort e o awk para usar | como separador
  • -k2 -k1 : classificar por segundo e, em seguida, primeiro campo
  • | na linha de ordenação deve ser o último caractere na linha
  • $1 < 8000 { a[$2]++ ; print } se abaixo de 8000, linhas de impressão e lembrar valor de $ 2
  • $1 >= 8000 { ... } se acima, armazene o maior valor
  • END { for ( i in u ) print u[i] ;} ao sair, despejar todo o valor

  • talvez seja necessário classificar novamente.

  • a condição da linha 2 pode ser simplificada (por ter condição fora de {})

  • alguma linha no seu teste tem 9 campos.

observe que o comando pode ser alinhado

... | sort -n -t\| -k2 -k1  | awk -F\| '...'
    
por 29.05.2016 / 11:27