Search code examples
bashubuntuprintfcat

The newline (\n) is not working in END block in bash


I need to define the "\n" in END block as it will be passed to other bash script as an argument.

I have added an empty newline at the begin and at the end. But only the begin empty line (\n) is working and the end empty line (\n) is not working.

Here is the test script:

string="$(cat <<"END"

foo
the "newline(\n)" in "END" before the foo is working
but "newline(\n)" in "END" after the bar is not working
bar

END
)"

echo ""
echo "--- method 1 - define \n in END block ---"
echo ""

printf "%s" "first line in single line (method 1)"
printf "%s" "$string"
printf "%s" "last line in single line (method 1)"

echo ""
echo ""
echo "--- method 2 - define \n in printf ---"
echo ""

printf "%s" "first line in single line (method 2)"
printf "%s\n" "$string"
printf "%s" "last line in single line (method 2)"

Here is the output:

--- method 1 - define \n in END block ---

first line in single line (method 1)
foo
the "newline(\n)" in "END" before the foo is working
but "newline(\n)" in "END" after the bar is not working
barlast line in single line (method 1)

--- method 2 - define \n in printf ---

first line in single line (method 2)
foo
the "newline(\n)" in "END" before the foo is working
but "newline(\n)" in "END" after the bar is not working
bar
last line in single line (method 2)

Here is the expected output:

--- method 1 - define \n in END block ---

first line in single line (method 1)
foo
the "newline(\n)" in "END" before the foo is working
but "newline(\n)" in "END" after the bar is not working
bar
last line in single line (method 1)

How to set the "\n" in the END block for making it work with method 1?

Update:

I tried to use variable inside the method provided by @tripleee:

var1="hello world"

string='
foo
the "newline(\n)" in "END" before the foo is working
but "newline(\n)" in "END" after the bar is not working

$var1

bar

'

printf "%s" "$string"

Here is the output:

foo
the "newline(\n)" in "END" before the foo is working
but "newline(\n)" in "END" after the bar is not working

$var1

bar

The $var1 is not replaced by the real content.

If I switch to the double quotes ("), then it must be use many escape characters (\") inside the "long long long and complex..." content.

How to make $var1 working with this method (without END block)?


Solution

  • That's crazy. The simple and obvious syntax is

    string='
    foo
    the "newline(\n)" in "END" before the foo is working
    but "newline(\n)" in "END" after the bar is not working
    bar
    
    '
    

    If you need variable interpolation inside the quoted string, use double quotes instead of single. Then, you will have to backslash-escape any literal double quotes, backslashes, dollar signs, or backticks (`). You can also use different quotes next to each other:

    string='
    foo
    the "newline(\n)" in "END" before the foo is working
    but "newline(\n)" in "END" after the bar is not working
    
    '"$var1"'
    
    bar
    
    '
    

    This contains a long single-quoted string which contains literal backslashes and double quotes immediately adjacent to the double-quoted string "$var1" immediately adjacent to another single-quoted string with newlines and bar in it. The shell will join these into a single string after quote removal.

    The acute reason your attempt isn't working is that the shell will, by definition, trim final newlines from command substitutions.