Como posso deletar uma nova linha no bash?

7

Estou procurando algo que se comporta como o chomp do Perl. Estou procurando um comando que simplesmente imprima sua entrada, menos o último caractere se for uma nova linha:

$ printf "one\ntwo\n" | COMMAND_IM_LOOKING_FOR ; echo " done"
one
two done
$ printf "one\ntwo" | COMMAND_IM_LOOKING_FOR ; echo " done"
one
two done

(A substituição de comandos no Bash e Zsh exclui todas as novas linhas à direita, mas estou procurando algo que exclua uma nova linha no final).

    
por Flimm 04.07.2014 / 12:52

5 respostas

7

Isso deve funcionar:

printf "one\ntwo\n" | awk 'NR>1{print PREV} {PREV=$0} END{printf("%s",$0)}' ; echo " done"

O script sempre imprime a linha anterior em vez da atual, e a última linha é tratada de forma diferente.

O que faz mais detalhadamente:

  1. NR>1{print PREV} Imprimir linha anterior (exceto a primeira vez).
  2. {PREV=$0} Armazena a linha atual na variável PREV .
  3. END{printf("%s",$0)} Finalmente, imprima a última linha sem quebra de linha.

Observe também que isso removeria no máximo uma linha vazia no final (não há suporte para remover "one\ntwo\n\n\n" ).

    
por 04.07.2014 / 13:10
11

Você pode usar perl sem chomp :

$ printf "one\ntwo\n" | perl -0 -pe 's/\n\Z//'; echo " done"
one
two done

$ printf "one\ntwo" | perl -0 -pe 's/\n\Z//'; echo " done"
one
two done

Mas por que não usar o chomp em si:

$ printf "one\ntwo\n" | perl -pe 'chomp if eof'; echo " done"
    
por 04.07.2014 / 13:55
3

Se você quiser um equivalente exato a chomp , o primeiro método que me vem à mente é a solução do awk que o LatinSuD já publicou . Vou adicionar alguns outros métodos que não implementam chomp , mas implementam algumas tarefas comuns que o chomp é usado com frequência.

Quando você coloca algum texto em uma variável, todas as novas linhas no final são removidas. Então, todos esses comandos produzem a mesma saída de linha única:

echo "$(printf 'one\ntwo') done"
echo "$(printf 'one\ntwo\n') done"
echo "$(printf 'one\ntwo\n\n') done"
echo "$(printf 'one\ntwo\n\n\n\n\n\n\n\n\n\n') done"

Se você quiser acrescentar algum texto à última linha de um arquivo ou à saída de um comando, sed pode ser conveniente. Com o GNU sed e a maioria das outras implementações modernas, isso funciona mesmo se a entrada não terminar em uma nova linha¹; no entanto, isso não adicionará uma nova linha se já não houver uma.

sed '$ s/$/ done/'

¹ No entanto, isso não funciona com todas as implementações de sed: sed é uma ferramenta de processamento de texto, e um arquivo que não é vazio e não termina com um caractere de nova linha não é um arquivo de texto.

    
por 05.07.2014 / 14:38
0

Outra abordagem perl . Este lê toda a entrada na memória, por isso pode não ser uma boa ideia para grandes quantidades de dados (use cuonglm ou a abordagem awk para isso):

$ printf "one\ntwo\n" | perl -00pe 's/\n$//'; echo " done"
one
two done
    
por 22.07.2015 / 15:08
0

Eu peguei isso em um repositório do github em algum lugar, mas não consigo encontrar onde

delete-trailing-blank-lines-sed

#!/bin/bash
#
# Delete all trailing blank lines.
# From http://sed.sourceforge.net/sed1line.txt
#
# Version: 1.3.0
# Created: 2011-01-02
# Updated: 2015-01-25
# Contact: Joel Parker Henderson ([email protected])
# License: GPL
##
set -euf
sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'
    
por 03.08.2018 / 14:34