Como deletar a última coluna de um arquivo no Linux

Quero deletar a última coluna de um arquivo txt, embora não saiba qual é o número da coluna é. Como eu poderia 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 

Comentários

  • Existem muitas maneiras de fazer isso .. adicione um exemplo e sua saída esperada dele ..
  • @heemayl ok eu fiz
  • Obrigado..as colunas estão separadas por tabulação ou por espaço?
  • @heemayl espaço é delimitador
  • cut soa como a ferramenta para o trabalho.

Resposta

Com awk:

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

ou:

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

ou:

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

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

A primeira é 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 uma string vazia "". Portanto, a segunda parte (onde NF é decrementada) só acontece se NF não for 0.

A segunda parte (NF-=1 NF-- ou --NF) está apenas subtraindo um da variável NF. Isso evita que o último campo seja impresso, porque quando você altera um campo (removendo o último campo neste caso), awk reconstrói $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 awk expressão for avaliada como verdadeira sem qualquer ação associada, awk a ação padrão é print $0 .

Comentários

  • @JJoao: Ah, obrigado, esqueci --. Uma observação, atualmente, você precisa de ;1 para compatibilidade com POSIX.
  • Meu instinto inicial seria usar um loop for, mas ele é muito mais conciso e inteligente.
  • ' é importante notar que se você ' estiver usando um delimitador não padrão, você ' Terei de fazer algumas alterações. Supondo que , seja o seu delimitador: awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out
  • O efeito de decrementar NF é um comportamento indefinido por POSIX – você obterá saída diferente dependendo de qual awk você ' está executando. Alguns awks removerão o último campo como você deseja, alguns não farão absolutamente nada e outros podem relatar um erro de sintaxe ou qualquer outra coisa.

Resposta

Usando grep com PCRE:

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

Usando GNU sed:

$ sed -r "s/(.*)\s+[^\s]+$/\1/" file.txt 1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334 

Comentários

  • @ramin Claro. . você poderia perguntar como uma nova pergunta (é assim que este site funciona) 🙂
  • @ramin Fornece alguma restrição de tempo ou algum aviso?
  • diz que isso está fora de questão!
  • @ramin Ok … deixe-me entrar em contato com um administrador, pode ser que ele possa ajudá-lo com isso .. a propósito, você verificou algum controle de qualidade antigo em relação à sua pergunta? é uma possibilidade de que a pergunta já tenha sido feita e respondida.
  • Não ' faça perguntas super básicas como " como posso renomear um nome de arquivo no Linux ". Use o Google.

Resposta

Usando Perl:

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

Usando rev + cut:

rev in | cut -d " " -f 2- | rev 

Resposta

Usando GNU sed:

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

Mais geralmente, este funciona com BSD sed em OSX, bem como GNU sed:

sed "s/[[:space:]]\{1,\}[^[:space:]]\{1,\}$//" input.txt 

Resposta

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

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

ou por exemplocom um arquivo csv :

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

Vou rodar alguns benchmarks mais tarde se tiver tempo, mas com muita entrada, acho que isso 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úmero de campos e, em seguida, usa cut, que é otimizado para este trabalho.

Resposta

Portavelmente, você pode usar qualquer um destes:

sed "s/[[:space:]]*[^[:space:]]*$//" file awk "{sub(/[[:space:]]*[^[:space:]]*$/,"")}1" file 

Resposta

Usando o vim:

Abra o arquivo no vim

vim <filename> 

Vá para a primeira linha, caso o cursor seja colocado em qualquer outro lugar.

gg 

Crie uma macro chamada “q” qq, que vai para o final da linha atual $, depois volta para o último espaço F (F maiúsculo, seguido de ESPAÇO literal) e exclua da posição atual até o final da linha D vá para a próxima linha j e pare 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 ainda mais fácil:

99@q 

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

Resposta

Para pessoas que têm um problema semelhante, mas com separadores de campo diferentes, isso awk preservará o separador de campo corretamente:

$ cat file foo.bar.baz baz.bar.foo $ awk -F"." "sub(FS $NF,x)" file foo.bar baz.bar 

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *