44

The following examples show that a newline is added to a here-string.
Why is this done?

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

xxd -p <<<'a
'
# output: 610a0a
Peter.O
  • 32,426
  • 28
  • 115
  • 163

3 Answers3

46

The easy answer is because ksh is written that way (and bash is compatible). But there's a reason for that design choice.

Most commands expect text input. In the unix world, a text file consists of a sequence of lines, each ending in a newline. So in most cases a final newline is required. An especially common case is to grab the output of a command with a command susbtitution, process it in some way, then pass it to another command. The command substitution strips final newlines; <<< puts one back.

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

Bash and ksh can't manipulate binary data anyway (it can't cope with null characters), so it's not surprising that their facilities are geared towards text data.

The <<< here-string syntax is mostly only for convenience anyway, like << here-documents. If you need to not add a final newline, use echo -n (in bash) or printf and a pipeline.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
  • Much more thorough than my answer. – Mike Sep 06 '11 at 00:02
  • 2
    Bash may have borrowed here-strings from ksh93, but ksh in turn borrowed them from zsh, which got them from the Plan 9 shell *rc*. – Mark Reed Jan 07 '14 at 22:04
  • 2
    `<<<` was introduced to the Bourne world by `zsh`, not `ksh`. And it was inspired by a similar operator in the Unix port of `rc` which did _not_ add that extra newline character. Interestingly, the `=(<< – Stéphane Chazelas Nov 06 '15 at 17:21
  • If you wonder about the interest in this answer is because of [this question in SO](http://stackoverflow.com/q/37728699/1983854). – fedorqui Jun 09 '16 at 14:41
  • 1
    Is there any way to write the here-string (without using any other utility like `printf`, etc) avoiding the tailing newline in `bash`? Like @StéphaneChazelas pointed is possible in `zsh`. – Cristian Todea Jun 20 '18 at 15:47
  • @CTodea If you want to avoid a pipe operator, you can use `< <(echo -n …)`. This doesn't use any external utility either (`echo` is a builtin, and so is `printf`). But it does basically the same thing as `echo -n … |` (same number of processes, same impact on error handling) and it's rather less readable. – Gilles 'SO- stop being evil' Jun 20 '18 at 16:47
  • Maybe a link to manual to back it up would be useful https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Here-Strings – Jakub Bochenski May 11 '21 at 13:49
5

One scenario in which it is practical to have newlines appended to here-strings is when using the read command when set -e mode is active. Recall that set -e causes a script to terminate when it (more or less) encounters statements that generate a non-zero status code. Consider that read generates a non-zero status code when it encounters a string without newlines:

#!/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
  • 421
  • 5
  • 5
-4

I think that's the only way to get a newline at the end of a here-string, proof:

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

It would appear that the here-string operator strips newlines unless they are given in the syntax you submitted.

Mike
  • 385
  • 1
  • 7