Hard to read:
This looks way too bash-like :) (hard to read) for my general taste:
cat << EndOfMessage
This is line 1.
This is line 2.
Line 3.
EndOfMessage
Better, easier-to-read:
Let's get something a little more Pythonic (this is still bash):
text="this is line one
this is line two
this is line three\n"
dedent text
printf "$text" # print to screen
printf "$text" > file.txt # print to a file
Ah...that's better. :) It reminds me of Python's textwrap.dedent()
function which I use here.
Here is what the magic dedent
function looks like:
dedent() {
local -n reference="$1"
reference="$(echo "$reference" | sed 's/^[[:space:]]*//')"
}
Sample output to screen:
this is line one
this is line two
this is line three
WithOUT calling dedent text
first`, the output would look like this:
this is line one
this is line two
this is line three
The variable text
is passed to dedent
by reference, so that what is modified inside the function affects the variable outside the function.
For more details and explanation and references, see my other answer here: Equivalent of python's textwrap dedent in bash
Problem with your original attempt
OP's quote (with my emphasis added):
I'm positive that there is no space after each \n
, but how does the extra space come out?
Your original attempt was this:
text="this is line one\n
this is line two\n
this is line three"
echo -e $text
...but your output had an extra space before the 2nd and 3rd line. Why?
By deduction and experimentation, my conclusion is that echo
converts the actual newline at the end of the line (the one you got when you actually pressed Enter) into a space. That space therefore shows up before the line just after each \n
in the text.
So, the solution is to escape the real newline at the end of each line by putting a backslash \
at the end of any line within the quotes of your string, like this:
text="this is line one\n\
this is line two\n\
this is line three"
echo -e "$text"
Do NOT put a space before those trailing backslashes (like this: text="this is line one\n \
) or that space will go right back into your output and cause you the same problem with the extra space!
OR, just use my technique with the dedent
function above, which also has the added functionality of being able to indent with your code to look really pretty and nice and readable.