echo a file as a single line with \n's
Solution 1
The solution I used was.
< file.txt sed '$!G' | paste -sd '\\n' -
sed '$!G'
appends an empty line to each line of input except the last ($
) one.paste -sd '\\n'
pastes those resulting lines alternatively with backslash andn
. And adds a newline in the end to result in valid text output.
Solution 2
Using the Perl sledgehammer:
$ perl -pe 's/\n/\\n/' < file.txt ; echo
The echo
is there to print a trailing newline just in case it's wanted for display purposes. This changes the NL on the last line to \n
too.
Or a rather straightforward solution in just Bash, assuming the file doesn't contain any embedded NUL bytes. Though note that this loads the whole file in memory:
$ IFS= read -r -d '' text < file.txt; printf '%s\n' "${text//$'\n'/\\n}"
Solution 3
Beware of a few special cases you may need to consider here. Let's take as example 4 files:
file1
an empty filefile2
a file with a single newline () character (one empty line)file3
a proper text file like:foo bar
file4
a file with the last line non-delimited:foo bar
If you want:
file1
: emptyfile2
:\n
file3
:foo\nbar\n
file4
:foo\nbar
(for instance so that you can reconstruct the file by passing the output to printf %b
).
Then, you could do:
perl -pe 's/\n/\\n/; END{print "\n" if $.}' < file
Or with GNU awk
:
gawk '{printf "%s", $0 (RT ? "\\n" : "")}
END{if (NR) print ""}' < file
You can adapt if you want to ignore the delimiter of the last line if any, or don't want the trailing newline, but then you may want to test on those 4 different cases that it does what you want as you'll probably find that you need to have special treatments for some of them.
For instance, your
< file sed '$!G' | paste -sd '\\n' -
solution to ignore the delimiter of the last line produces one empty line for both file1
and file2
(and for not-properly-delimited text (file4
) may not work properly with all sed
/paste
implementations as those are meant to deal with valid text).
perl -pe 's/\n?$/eof ? "\n" : "\\n"/e' < file
may be more portable, and maybe slightly better for file1
and file2
which it would leave untouched.
Solution 4
tr
alone can't do it since you need to replace one character by two characters. sed
alone can't do it easily since it outputs a newline at the end of everything it prints. But you can do it by combining the two: add \n
at the end of every line, then remove the line breaks.
sed 's/$/\\n/' | tr -d '\n'
This produces a file that ends with \n
and no line break. If you want a newline at the very end, echo it:
{ sed 's/$/\\n/' | tr -d '\n'; echo; }
(Note that this turns an empty file into a file with a single empty line.) If you don't want the last \n
, sed it away:
sed 's/$/\\n/' | tr -d '\n' | sed 's/\\n$//'
Related videos on Youtube
Louise McMahon
Updated on September 18, 2022Comments
-
Louise McMahon almost 2 years
I have a multi line text file that I want to echo out as a single line file where the new lines are shown as \n.
Any pointers would be great.
-
Sundeep almost 7 yearssomething like this?
seq 5 | awk -v ORS='\\n' '1'
-
-
Sundeep almost 7 yearsyou can avoid the echo using
perl -pe 's/\n/\\n/; END{print "\n"}'
or if last\n
is not needed,perl -pe 's/\n/\\n/ if !eof'
-
Louise McMahon almost 7 yearsI ended up using the solution in your original comment ` cat file.txt | sed '$!G' | paste -sd '\\n'`
-
Stéphane Chazelas almost 7 years@Louise, OK, though see edit.
-
ilkkachu almost 7 years@Sundeep, I know, but that's longer and uglier. :D I'm not sure what to think about the last line.