Como remover linhas com um número menor que 60 na coluna 3?

6

Eu tenho um arquivo grande. Eu preciso remover todas as linhas em um arquivo que tem um número menor que 60 na coluna 3.

Arquivo de exemplo:

35110   Bacteria(100)   Proteobacteria(59)  Alphaproteobacteria(59)
12713   Bacteria(100)   Bacteroidetes(100)  Bacteroidia(100)

Saída desejada:

12713   Bacteria(100)   Bacteroidetes(100)  Bacteroidia(100)
    
por Manoj Kumar 08.02.2018 / 21:16

4 respostas

9

Não há necessidade de extensões do Gawk:

awk -F '[()]' '$4 >= 60'

Aqui, o tokenizer de campo awk especificado através de -F é um conjunto de regex [] : os campos são separados por um parêntese de abertura ou fechamento, daí você vê que o número da sua terceira coluna é o 4º campo awk .

    
por Steven Penny 09.02.2018 / 02:38
4

Você pode usar awk (na verdade, deve ser a implementação do GNU AWK gawk , não mawk , que contém menos recursos - talvez seja necessário instalá-lo sudo apt install gawk ) para este trabalho:

gawk '{match($3,/\((.+)\)/,m);if(m[1]>=60){print $0}}' MY_FILE

Agora, embora isso seja como magia negra para o olho destreinado, a lógica é simples:

  • Para cada linha, execute o material dentro das chaves mais externas:
  • Primeiro, match($3, /\((.+)\)/, m) corresponde à expressão regular \((.+)\) (que corresponde a um colchete de abertura e fechamento, armazenando o conteúdo entre colchetes como primeiro grupo de captura) em relação à terceira coluna $3 da linha processada de entrada e armazena a matriz de correspondência resultante na variável m .
  • Em seguida, verifique a condição if (m[1] >= 60) , ou seja, se o valor do primeiro grupo de captura da correspondência (o que estiver entre os colchetes na entrada) for maior ou igual a 60. Se isso for verdade, do {print $0} , que simplesmente imprime toda a linha atualmente processada.
por Byte Commander 08.02.2018 / 21:55
4

Aqui está uma alternativa perl

perl -alne 'print unless $F[2] =~ /\((\d+)\)$/ && $1 < 60'
  • corresponde e captura uma sequência entre parênteses de dígitos decimais no final do terceiro campo (com índice zero)
  • se uma correspondência for encontrada, teste o valor numérico do grupo capturado e imprima de acordo

Ex.

$ perl -alne 'print unless $F[2] =~ /\((\d+)\)$/ && $1 < 60' file
12713   Bacteria(100)   Bacteroidetes(100)  Bacteroidia(100)

Observe que isso implementa a lógica "remover todas as linhas em um arquivo com um número menor que 60 na coluna 3" como indicado na sua pergunta - o que é um pouco diferente das linhas de impressão que possuem um número maior ou igual a 60.

Se os seus arquivos estiverem realmente separados por vírgulas (em vez de delimitados por espaços em branco, conforme mostrado na sua pergunta), será necessário alterar o delimitador, por exemplo,

perl -F, -lne 'print unless $F[2] =~ /\((\d+)\)$/ && $1 < 60'
    
por steeldriver 08.02.2018 / 23:41
0

Se você não quer aprender / usar ferramentas de linha de comando, é melhor abrir o arquivo no LibreOffice Calc e filtrar os dados (o Calc suporta arquivos separados por tabulações).

Se você conhece qualquer linguagem de programação, então é trivial escrever um pequeno programa para filtrar os dados.

Mas se você tiver um grande conjunto de dados para processar, usar um DBMS como o MySQL seria mais fácil, rápido e intuitivo.

    
por Karan Karan 08.02.2018 / 23:37