Search code examples
bashcommandoutputnewlinetrim

bash: $(...) trims trailing empty lines. How to properly assign to variable a command's output?


[Context]

Eg.1:

a="$(echo $'\n\n\n\n\n')"; echo ${#a};

I see: 0

Eg.2:

a="$(echo $'\n\n\n\n\n_')"; echo ${#a};

I see: 6

[Problem / Question]

I need to keep all the trailing empty lines in the assignment to variable. How to rewrite the «Eg.1»? If it's possible, give the simplest solution.

[Solution]

I'll accept the variant 2 of the rici's answer.

to() 
{
    local to=${1};

    IFS= read -rd '' ${to}; 
    printf -v ${to} "${!to%$'\n'}";
};

…
# a="$(echo $'\n\n\n\n\n')"; # wrong

to a < <(echo $'\n\n\n\n\n');
…

# aVariable="$(some_command arg_1 … arg_n)"; # wrong assignment
to aVariable < <(some_command arg_1 … arg_n);

P.S. The lengths of the both lines (i.e., of the wrong line and of the valid line) above are almost equal.


Solution

  • Here are two solutions which will work with arbitrary commands:

    1) add the extra character at the end and then delete it:

    $ a="$(printf '\n\n\n\n\n'; echo _)"; a="${a%?}"; echo ${#a}
    5
    

    2) use read:

    $ IFS= read -rd '' a < <(printf '\n\n\n\n\n'); echo ${#a}
    5
    

    The space between -d and '' is necessary; you need to provide an empty argument to the -d option, and -d'' doesn't do that.