Como excluir a última coluna de um arquivo no Linux

22

Desejo excluir a última coluna de um arquivo txt, embora não saiba qual é o número da coluna. Como eu pude fazer isso?

Exemplo:

Entrada:

1223 1234 1323 ... 2222 123
1233 1234 1233 ... 3444 125
0000 5553 3455 ... 2334 222

E eu quero que minha saída seja:

1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334
    
por zara 07.10.2015 / 08:06

7 respostas

36

com awk :

awk 'NF{NF-=1};1' <in >out

ou:

awk 'NF{NF--};1' <in >out

ou:

awk 'NF{--NF};1' <in >out

Embora isso pareça um vodu, funciona. Existem três partes para cada um desses comandos awk.

O primeiro é NF , que é uma pré-condição para a segunda parte. NF é uma variável que contém o número de campos em uma linha. No AWK, as coisas são verdadeiras se não forem 0 ou se a string vazia "" . Portanto, a segunda parte (em que NF é diminuído) só acontece se NF não for 0.

A segunda parte ( NF-=1 NF-- ou --NF ) está subtraindo apenas uma da variável NF . Isso impede que o último campo seja impresso, porque quando você altera um campo (removendo o último campo nesse caso), awk re-construct $0 concatena todos os campos separados por espaço por padrão. $0 não continha mais o último campo.

A parte final é 1 . Não é mágico, é apenas usado como uma expressão que significa true . Se uma expressão awk for avaliada como verdadeira sem nenhuma ação associada, a ação awk padrão será print $0 .

    
por 07.10.2015 / 08:13
16

Usando grep com o PCRE:

$ grep -Po '.*(?=\s+[^\s]+$)' file.txt 
1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

Usando o GNU sed :

$ sed -r 's/(.*)\s+[^\s]+$//' file.txt 
1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334
    
por 07.10.2015 / 08:18
8

Usando o Perl:

perl -lane '$,=" ";pop(@F);print(@F)' in

Usando rev + cut :

rev in | cut -d ' ' -f 2- | rev
    
por 07.10.2015 / 12:04
4

Usando o GNU sed:

sed -r 's/\s+\S+$//' input.txt

Mais geralmente, este funciona com o BSD sed no OSX, assim como o GNU sed:

sed 's/[[:space:]]\{1,\}[^[:space:]]\{1,\}$//' input.txt
    
por 07.10.2015 / 22:51
1

Se o delimitador é sempre um único caractere (então dois ou mais delimitadores consecutivos designam campos vazios), você poderia head apenas a primeira linha de seu arquivo de entrada, contar os delimitadores ( n delimitadores significa número de campos é n+1 ) use cut para imprimir do campo 1 st até o campo n th (segundo para o último), por exemplo com entrada delimitada por tabulações:

n=$(head -n 1 infile | tr -dc \t | tr \t \n | wc -l)
cut -f1-$n infile > outfile

ou por ex. com um arquivo csv :

n=$(head -n 1 infile | tr -dc , | tr , \n | wc -l)
cut -d, -f1-$n infile > outfile

Eu executarei alguns benchmarks mais tarde, se eu tiver tempo, mas com uma grande contribuição, acho que esta solução deve ser mais rápida do que outras soluções que usam regex, já que esta faz o processamento mínimo na primeira linha para obter o não. de campos e, em seguida, usa cut , que é otimizado para este trabalho.

    
por 08.10.2015 / 18:25
1

Portavelmente você pode usar um destes:

sed 's/[[:space:]]*[^[:space:]]*$//' file

awk '{sub(/[[:space:]]*[^[:space:]]*$/,"")}1' file
    
por 29.10.2018 / 12:44
0

Usando o vim:

Abra o arquivo no vim

vim <filename> 

Vá para a primeira linha, caso o cursor esteja em outro lugar.

gg

Crie uma macro com o nome "q" qq , que vai para o verso da linha atual $ , e volte ao último espaço F (capital F, seguido pelo espaço literal) e apague do atual a posição até o fim da linha D vai para a próxima linha j e para a gravação da macro com q .

qq$F Djq

Agora podemos repetir nossa macro com @q para cada linha.
Também podemos pressionar @@ para repetir a última macro ou até mais fácil:

99@q

para repetir a macro 99 vezes.
Nota: O número não deve corresponder exatamente às linhas.

    
por 10.10.2015 / 17:51