Search code examples
bashshellechoposixsubshell

POSIX/Bash pad variable with trailing newlines


I have a variable with some lines in it and I would like to pad it with a number of newlines defined in another variable. However it seems that the subshell may be stripping the trailing newlines. I cannot just use '\n' with echo -e as the lines may already contain escaped chars which need to be printed as is.

I have found I can print an arbitrary number of newlines using this.

n=5
yes '' | sed -n "1,${n}p;${n}q"

But if I run this in a subshell to store it in the variable, the subshell appears to strip the trailing newlines.

I can approximate the functionality but it's clumsy and due to the way I am using it I would much rather be able to just call echo "$var" or even use $var itself for things like string concatenation. This approximation runs into the same issue with subshells as soon as the last (filler) line of the variable is removed.

This is my approximation

n=5
var="test"
#I could also just set n=6
cmd="1,$((n+1))p;$((n+1))q"
var="$var$(yes '' | sed -n $cmd; echo .)"

#Now I can use it with
echo "$var" |  head -n -1

Essentially I need a good way of appending a number of newlines to a variable which can then be printed with echo.

I would like to keep this POSIX compliant if at all possible but at this stage a bash solution would also be acceptable. I am also using this as part of a tool for which I have set a challenge of minimizing line and character count while maintaining readability. But I can work that out once I have a workable solution


Solution

  • Command substitutions with either $( ) or backticks will trim trailing newlines. So don't use them; use the shell's built-in string manipulation:

    n=5
    var="test"
    while [ "$n" -gt 0 ]; do
        var="$var
    "
        n=$((n-1))
    done
    

    Note that there must be nothing after the var="$var (before the newline), and nothing before the " on the next line (no indentation!).