Bash: tira a quebra de linha à direita da saída

189

Quando executo comandos no Bash (ou para ser específico wc -l < log.txt), a saída contém uma quebra de linha após ela. Como faço para me livrar dele?

hexacianida
fonte

Respostas:

251

Se a saída esperada for uma única linha , você poderá simplesmente remover todos os caracteres de nova linha da saída. Não seria incomum canalizar para o utilitário 'tr' ou para Perl, se preferir:

wc -l < log.txt | tr -d '\n'

wc -l < log.txt | perl -pe 'chomp'

Você também pode usar a substituição de comando para remover a nova linha à direita:

echo -n "$(wc -l < log.txt)"

printf "%s" "$(wc -l < log.txt)"

Observe que não concordo com a decisão do OP de escolher a resposta aceita. Eu acredito que se deve evitar o uso de 'xargs' sempre que possível. Sim, é um brinquedo legal. Não, você não precisa aqui.


Se a saída esperada puder conter várias linhas , você terá outra decisão a tomar:

Se você deseja remover vários caracteres de nova linha do final do arquivo, use novamente a substituição do cmd:

printf "%s" "$(< log.txt)"

Se você deseja remover estritamente o último caractere de nova linha de um arquivo, use Perl:

perl -pe 'chomp if eof' log.txt


Note que se você tem certeza de que possui um caractere de nova linha à direita que deseja remover, você pode usar 'head' dos coreutils do GNU para selecionar tudo, exceto o último byte. Isso deve ser bem rápido:

head -c -1 log.txt

Além disso, para garantir a integridade, você pode verificar rapidamente onde seus caracteres de nova linha (ou outros caracteres especiais) estão em seu arquivo usando 'cat' e o sinalizador 'show-all'. O caractere do cifrão indicará o final de cada linha:

cat -A log.txt
Steve
fonte
Isso retira TODAS as novas linhas da saída, não apenas a nova linha à direita, como o título pede.
Cody A. Ray
@ CodyA.Ray: Você deve concordar, porém, que a pergunta descreve um comando específico que apenas produzirá uma única linha de saída. No entanto, atualizei minha resposta para se adequar ao caso mais geral. HTH.
Steve
3
Isso seria melhor se as opções curtas fossem substituídas por longas. As opções longas ensinam e funcionam, por exemplo tr --delete '\n'.
Elias Lynn
1
Eu também fiz| tr -d '\r'
AlikElzin-kilaka
Vale ressaltar que a solução de substituição do cmd pode levar a uma linha muito longa se o arquivo for muito grande.
Php
88

Mão única:

wc -l < log.txt | xargs echo -n
Satya
fonte
24
Melhor:echo -n `wc -l log.txt`
Satya
9
Por que é melhor executar comandos em backticks do que usar um pipe?
Matthew Schinckel
2
Isso não apenas removerá as novas linhas à direita, mas também compactará os espaços em branco consecutivos (mais precisamente, conforme definido por IFS) em um espaço. Exemplo echo "a b" | xargs echo -n:; echo -n $(echo "a b"). Isso pode ou não ser um problema para o caso de uso.
Musiphil 15/09/14
14
Pior, se a saída começar -e, ela será interpretada como a opção para echo. É sempre mais seguro de usar printf '%s'.
Musiphil 15/09/14
1
xargsé muito lento no meu sistema (e suspeito que também esteja em outros sistemas), então printf '%s' $(wc -l log.txt)pode ser mais rápido, pois printfgeralmente é um componente interno (também porque não há redirecionamento de informações). Nunca use backticks, eles foram descontinuados nas versões mais recentes do POSIX e apresentam inúmeras desvantagens.
yyny
14

Também há suporte direto para remoção de espaços em branco na substituição de variáveis ​​do Bash :

testvar=$(wc -l < log.txt)
trailing_space_removed=${testvar%%[[:space:]]}
leading_space_removed=${testvar##[[:space:]]}
Andrey Taranov
fonte
1
Você também pode usartrailing_linebreak_removed=${testvar%?}
PairedPrototype
Observe que, se você estiver usando a substituição de comandos, não precisará fazer nada para remover as novas linhas à direita. O Bash já faz isso como parte da substituição de comando: gnu.org/software/bash/manual/html_node/…
Michael Burr
10

Se você atribuir sua saída a uma variável, bashremove automaticamente os espaços em branco:

linecount=`wc -l < log.txt`
nneonneo
fonte
10
As novas linhas à direita são removidas, para ser exato. É a substituição de comando que os remove, não a atribuição de variáveis.
chepner
2
Vi no Cygwin bash o espaço em branco à direita não removido ao usar $ (cmd / c echo% VAR%). Nesse caso, eu tive que usar $ {var %% [[: space:]]}.
Andrey Taranov 8/11
1
Nota: não é a atribuição da variável, mas a expansão da expressão que remove as novas linhas.
Ciro Santilli escreveu
10

printf já recorta a nova linha à direita para você:

$ printf '%s' $(wc -l < log.txt)

Detalhe:

  • printf imprimirá seu conteúdo no lugar do %smarcador de posição da cadeia.
  • Se você não solicitar que imprima uma nova linha ( %s\n), isso não acontecerá.
zero2cx
fonte
7
Se você colocar aspas duplas em torno do comando "$(command)", as novas linhas internas serão preservadas - e somente a nova linha à direita será removida. O shell está fazendo todo o trabalho aqui - printfé apenas uma maneira de direcionar os resultados da substituição de comando para stdout.
Brent Bradburn
2
Não é o printf que está removendo a nova linha aqui, é o shell que está fazendo isso com a $( )construção. Aqui está a prova:printf "%s" "$(perl -e 'print "\n"')"
Flimm
Novamente, vale a pena notar que a linha de comando resultante pode se tornar muito longa.
Php
Esta é uma solução conveniente, com sugestão de @ Nobar:$ printf '%s' "$(wc -l < log.txt)"
Ilias Karim
10

Se você deseja remover apenas a última nova linha , passe por:

sed -z '$ s/\n$//'

sednão adicionará um \0ao final do fluxo se o delimitador estiver definido como NULvia -z, enquanto que para criar um arquivo de texto POSIX (definido para terminar em a \n), ele sempre produzirá um final \nsem -z.

Por exemplo:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//'; echo tender
foo
bartender

E para provar que não foi NULadicionado:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//' | xxd
00000000: 666f 6f0a 6261 72                        foo.bar

Para remover várias linhas novas à direita , passe por:

sed -Ez '$ s/\n+$//'
Tom Hale
fonte
Suponho que seja uma extensão GNU, o Mac sednão fornece -z.
Spidey
7

Se você quiser imprimir qualquer coisa no Bash sem fim de linha, faça o eco com a -nchave.

Se você já tiver uma variável, faça o eco com a nova linha à direita cortada:

    $ testvar=$(wc -l < log.txt)
    $ echo -n $testvar

Ou você pode fazer isso em uma linha, em vez disso:

    $ echo -n $(wc -l < log.txt)
Rastislav Hasicek
fonte
2
A variável é tecnicamente desnecessária. echo -n $(wc -l < log.txt)tem o mesmo efeito.
chepner