Exclusão de coluna verdadeira, não selecionando todas as colunas que você deseja

6

Eu sei que esta é uma pergunta simples e de muitas maneiras foi respondida antes, porém todos os usos que eu vi do awk, sed, grep etc foram selecionando e imprimindo as colunas que você deseja. Em um caso em que há um número desconhecido de colunas que você deseja e uma coluna específica que você não deseja, como você remove a coluna que não deseja?

Você simplesmente seleciona as colunas antes e depois seleciona as n colunas depois da coluna que você não quer? Não existe apenas uma simples função delete n da coluna?

Eu não tenho um exemplo, pois é mais uma questão de curiosidade, mas posso desenhar um, se necessário.

    
por Giles 27.05.2016 / 18:06

4 respostas

2

Embora awk não tenha uma função para excluir um campo de uma linha, você pode definir colunas específicas para a string vazia.

No entanto, há um truque comum que pode ser usado para excluir colunas (por exemplo, colunas 5 e 7):

awk '{$5=$7="" ; $0=$0;$1=$1}1'

O $0=$0;$1=1 define $ 0 para si e $ 1 para si mesmo. Isso tem o efeito colateral de remover qualquer delimitador de campo extra (isto é, os delimitadores que existiriam imediatamente após os campos agora vazios $ 5 e $ 7)

NOTA: isso também converterá todos os separadores de campo em $ 0 para qualquer que seja o OFS (Output Field Separator) definido atualmente (por exemplo, com padrão FS e OFS, ele converterá várias guias e espaços entre os campos para um espaço único

Com perl , é muito mais fácil. tem uma função ( splice() ) para excluir colunas de um array:

perl -lane 'BEGIN{$,=" "}; splice(@F,4,1); splice(@F,5,1); print @F'

$,=" " define o separador do campo de saída como um único espaço.

Notas:

  1. as matrizes de perl começam em 0, não 1. então @F[4] é a quinta coluna.

  2. isso exclui a coluna 5, então a segunda coluna (7) que queremos excluir agora é a sexta coluna, e é por isso que o segundo splice exclui @F[5] .

Para evitar qualquer confusão potencial aqui, exclua as colunas na ordem inversa:

perl -lane 'BEGIN{$,=" "}; splice(@F,6,1); splice(@F,4,1); print @F'

ou você pode usar um loop:

perl -lane 'BEGIN{$,=" "}; foreach $c (7,5) {splice(@F,$c-1,1)}; print @F'

BTW, se você quiser excluir apenas a coluna primeiro ou último , poderá usar shift @F ou pop @F .

Saída:

com a seguinte entrada:

1 2 3 4 5 6 7 8 9 10
10  9   8   7   6   5   4   3   2   1
a b c d e f h i j k

Todos dos scripts acima produzirão a seguinte saída:

1 2 3 4 6 8 9 10
10 9 8 7 5 3 2 1
a b c d f i j k
    
por 28.05.2016 / 06:05
3

Ok, então você pode usar o comando cut, mas ainda não é a exclusão da coluna, a seleção das colunas que você quer, que tem uma opção de coluna infinita. Então, uma solução se você quiser selecionar a segunda coluna e depois cada coluna de 4 em diante é:

corte -f 2,4- arquivo.txt

No entanto, ainda estou interessado em saber se existe um comando de exclusão real?

    
por 27.05.2016 / 20:56
2

Depende do que você quer dizer com colunas. Se por colunas você realmente quer dizer colunas de caracteres e não campos delimitados, o obscuro colrm permite especifique a coluna inicial ou as colunas inicial e final de um intervalo de colunas a serem excluídas. Não há como excluir um número arbitrário de colunas não contíguas em uma invocação

    
por 27.05.2016 / 21:49
1

Eu acredito que o comando de corte funcionaria para você, talvez?

Encontrou isto numa resposta anterior: link

Um pouco mais sobre o comando cut: link link

    
por 27.05.2016 / 18:16