The following code best describes the situation. Why is the last line not outputting the trailing newline char? Each line’s output is shown in the comment. I’m using GNU bash, version 4.1.5
echo -n $'anbn' | xxd -p # 610a620a
x=$'anbn' ; echo -n "$x" | xxd -p # 610a620a
echo -ne "anbn" | xxd -p # 610a620a
x="$(echo -ne "anbn")" ; echo -n "$x" | xxd -p # 610a62
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
The command substitution function $() (and its cousin the backtick) specifically removes trailing newlines. This is the documented behavior, and you should always be aware of it when using the construct.
Newlines inside the text body are not removed by the substitution operator, but they may also be removed when doing word splitting on the shell, so how that turns out depends on whether you used quotes or not. Note the difference between these two usages:
$ echo -n "$(echo -n 'anb')"
a
b
$ !! | xxd -p
610a62
$ echo -n $(echo -n 'anb')
a b
$ !! | xxd -p
612062
In the second example, the output wasn’t quoted and the newline was interpreted as a word-split, making it show up in the output as a space!
Method 2
When using command substitution, the shell executes the commands in a subshell, returning their stdout. in this process, the IFS characters loss their significance (if they are not quoted), as the commend returns plain split words, so the trailing ones are removed. For example:
$ echo "$(echo -e 'n')" | wc 1 0 1 $ echo -e 'n' | wc 2 0 2
and more practically, pwd will work even if your directory name has a newline in between, but $(pwd) will not.
The usual workaround is to add something at the end of your command and strip it thereafter.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0