Por que uma string bash here adiciona um caractere de nova linha à direita?

34

Os exemplos a seguir mostram que uma nova linha é adicionada a uma string aqui .
Por que isso é feito?

xxd -p <<<'a'  
# output: 610a

xxd -p <<<'a
'
# output: 610a0a
Peter.O
fonte

Respostas:

38

A resposta fácil é porque o ksh é escrito dessa maneira (e o bash é compatível). Mas há uma razão para essa escolha de design.

A maioria dos comandos espera entrada de texto. No mundo unix, um arquivo de texto consiste em uma sequência de linhas, cada uma terminando em uma nova linha . Portanto, na maioria dos casos, é necessária uma nova linha final. Um caso especialmente comum é pegar a saída de um comando com uma suspeita de comando, processá-lo de alguma maneira e depois passá-lo para outro comando. A substituição de comando retira novas linhas finais; <<<coloca um de volta.

tmp=$(foo)
tmp=${tmp//hello/world}
tmp=${tmp#prefix}
bar <<<$tmp

Bash e ksh não podem manipular dados binários de qualquer maneira (ele não pode lidar com caracteres nulos), portanto, não é de surpreender que suas instalações sejam voltadas para dados de texto.

A <<<sintaxe da string here é principalmente apenas por conveniência, como <<documentos here. Se você não precisar adicionar uma nova linha final, use echo -n(no bash) ou printfe um pipeline.

Gilles 'SO- parar de ser mau'
fonte
Muito mais completo do que minha resposta.
Mike
2
O Bash pode ter emprestado as strings here do ksh93, mas o ksh, por sua vez, as emprestou do zsh, que as obteve do shell do plano 9 rc .
Mark Reed
2
<<<foi introduzido no mundo Bourne por zsh, não ksh. E foi inspirado por um operador semelhante na porta Unix, rcque não adicionou esse caractere de nova linha extra. Curiosamente, o =(<<<text)operador não adiciona essa nova linha zsh.
Stéphane Chazelas
Se você se pergunta sobre o interesse nesta resposta, é por causa dessa pergunta no SO .
fedorqui
11
Existe alguma maneira de escrever a string here (sem usar qualquer outro utilitário como printf, etc), evitando a nova linha de cauda bash? Como @ StéphaneChazelas apontado é possível em zsh.
CTodea
3

Um cenário no qual é prático ter novas linhas anexadas às seqüências de caracteres here é quando se usa o readcomando quando o set -emodo está ativo. Lembre-se de que set -eum script é finalizado quando (mais ou menos) encontra instruções que geram um código de status diferente de zero. Considere que readgera um código de status diferente de zero quando encontra uma sequência sem novas linhas:

#!/bin/bash
set -e

# The following statement succeeds because here-strings append a newline:
IFS='' read -r <<< 'newline appended'
echo 'Made it here'

# The following statement fails because 'read' returns a non-zero status
# code when no newlines are encountered.
printf 'no newline' | IFS='' read -r
echo 'Did not make it here'
Dejay Clayton
fonte
-3

Eu acho que é a única maneira de obter uma nova linha no final de uma prova aqui:

xxd <<<`echo -ne "a\n"`

Parece que o operador da string aqui retira novas linhas, a menos que sejam fornecidas na sintaxe que você enviou.

Mike
fonte
4
É a substituição de comando que retira a nova linha final. Você pode simplificar isso para xxd <<<$(echo a).
Gilles 'SO- stop be evil'