t ou comando awk para inserir abas (delimitador) em posições específicas

1

Estou tentando analisar uma tabela com um número variável de delimitadores para converter em uma tabela de colunas iguais:

cluster=96\troot\tcellular organisms\tno_rank no_rank$

cluster=42\troot\tcellular organisms\tBacteria\tno_rank\tno_rank\tsuperkingdom$

cluster=362\troot\tcellular organisms\tBacteria\tProteobacteria\tno rank\tno rank\tsuperkingdom\tphylum$

cluster=12330\troot\tcellular organisms\tBacteria\tTerrabacteria\tFirmicutes\tClostridia\tClostridiales\tClostridiaceae\tClostridium\tno rank\tno rank\tsuperkingdom\tno rank\tphylum\tclass\torder\tfamily\tgenus$

A saída esperada é:

cluster=96\troot\tcellular organisms\t\t\t\t\t\t\t\tno_rank\tno_rank\t\t\t\t\t\t\t$

cluster=42\troot\tcellular organisms\tBacteria\t\t\t\t\t\t\tno_rank\tno_rank\tsuperkingdom\t\t\t\t\t\t$

cluster=362\troot\tcellular organisms\tBacteria\tProteobacteria\t\t\t\t\t\tno rank\tno rank\tsuperkingdom\tphylum\t\t\t\t\t$

cluster=12330\troot\tcellular organisms\tBacteria\tTerrabacteria\tFirmicutes\tClostridia\tClostridiales\tClostridiaceae\tClostridium\tno rank\tno rank\tsuperkingdom\tno rank\tphylum\tclass\torder\tfamily\tgenus$

"\ t" é um delimitador de tabulação e "$" é o fim da linha

    
por user3472737 10.11.2016 / 13:37

2 respostas

3

Usando o Awk com dois passes:

awk -F'\t' -v OFS='\t' 'FNR==NR {if (NF>a) {a=NF}; next} NF<a{$a=""} 1' file file

Isso adicionará as guias extras no fim das linhas com campos ausentes.

Com base nos seus dados de amostra exatos, acho que você está lidando com um problema impossível de resolver programaticamente. Se você precisar de guias extras em uma posição intermediária para garantir que os valores de no_rank acabem na coluna da direita, você precisará de alguma lógica mais sofisticada.

    
por 10.11.2016 / 14:09
0

Usando o Miller : eu respondi uma pergunta semelhante para CSV aqui mas, nesse caso, o comprimento máximo já estava disponível na linha de cabeçalho, portanto não houve necessidade de pesquisá-lo em outro lugar.

Nesse caso, onde o tamanho máximo pode estar em outro lugar, o melhor que eu pude fazer foi:

cat in.dat | mlr --nidx --fs tab --nidx put -q '
  @maxnf = max(@maxnf, NF);
  @records[NR] = $*; # Retain
  @counts[NR] = NF;

  end {
    for (i in @records) {
      @record = @records[i];
      for (j = @counts[i] + 1; j <= @maxnf; j += 1) { # add extra fields
        @record["x".j] = "";
      }
      emit @record;            # insert into the output record stream
    }
  }
'

Idéia é manter a lista de registros e o máximo de NF; então processe em um bloco final. Observe que isso usa recursos in head (não na versão 4.5.0 mais recente).

    
por 11.11.2016 / 14:14