No bash, quando uma saída é capturada em uma variável usando $(...)
, uma nova linha irritante é acrescentada. No entanto, tenho uma saída que às vezes termina em uma nova linha e às vezes não. Eu quero que a saída seja capturada como está.
No meu problema real, as strings podem conter várias linhas, mas a última pode ou não fechar com uma nova linha, e essa propriedade deve ser preservada.
No estilo desta resposta no Stack Exchange , meu exemplo de trabalho mínimo se parece com isso:
#!/bin/bash
newlinetest() {
if [ "$1" = 'with' ]; then
printf '%s\n' 'Text with newline'
else
printf '%s' 'Text without newline'
fi
}
s="$(newlinetest with ; printf '%s' 'x')"
s="${s%?}"
printf '%s%s%s\n' '(' "${s}" ')'
s="$(newlinetest without ; printf '%s' 'x')"
s="${s%?}"
printf '%s%s%s\n' '(' "${s}" ')'
Ele faz o que deveria fazer, mas IMHO isso parece um hack feio. Existe alguma outra maneira elegante de resolver isso? Talvez algo que envolva mapfile
ou read
? Uma solução sem ferramentas externas seria muito bem-vinda.
Na verdade, a substituição de comando remove as novas linhas à direita, não as anexa. Mas se você usar
echo
para imprimir a variável mais tarde, ela adiciona uma por padrão.Adicionar um trailing
x
ou algo parecido é de fato um pouco hack, mas provavelmente é a maneira mais fácil e funciona em todos os shells. Você pode torná-lo um pouco mais curto usandoecho x
em vez deprintf '%s' 'x'
.Como você mencionou
read
, você também pode usar algo assim (no Bash):Vou deixar para você decidir se isso é mais bonito do que isso:
Embora haja uma diferença de desempenho potencial entre os dois. No primeiro, a substituição do processo cria um pipe, que
read
lê um byte de cada vez para evitar a ultrapassagem de um delimitador (Isso não é relevante aqui, mas o shell não sabe disso.) A substituição do comando lerá em blocos maiores, e, portanto, é provável que seja mais rápido com uma grande saída.