2

Sometimes simplest things take your time in shell scripting like crazy.

Content='me \n you \n him \n'
echo $Content > Names.txt

When I open the Names.txt it has two empty lines at the end.

I want it to only have one empty line. The Content variable is calculated in a loop and in each iteration it adds a new line to it. Thus I can't change Content.

I can't use echo -n because it removes all new lines.

I can't remove the \n from my loop, because in that case all lines are concatenated to each other.

I tried Content=$(echo $Content | awk 'NR>1{print PREV} {PREV=$0} END{printf("%s",$0)}') to use awk to remove the trailing newline, but it does not work. I took it from an answer on this site.

I tried to use printf %s $Content > File.txt instead of echo -e, still no success.

How can I either remove the trailing newline from a given string variable or write it as is to the file and tell Linux not to append yet another line to it?

6
  • 1
  • if you have Content='me \n you \n him \n' and run echo -e "$Content" (or any echo that interprets backslash-escapes, like Bash with xpg_echo set, or the implementations in many other shells), the resulting output will end in him, a space and two newlines. The first newline terminates the line with the word him, so there'll be one empty line at the end, not two.
    – ilkkachu
    Jun 30 at 17:22
  • On the other hand, your variable will have zero newlines at the end, so you can't remove any. What that command assigns to the variable is a backslash and the letter n.
    – ilkkachu
    Jun 30 at 17:25
  • Happy not to see the duplicate hammer on this, but a little sad for the printf solutions.
    – mckenzm
    Jul 1 at 6:21
  • 1
    Hey, Saeed, you say this is bash, but your question's content says your shell does not behave like bash; could you verify it's bash? What happens when you echo $SHELL? What happens when you run echo $0? Jul 1 at 9:09

3 Answers 3

10

it's not Linux adding that second newline, it's your bash when you call echo!

So, the answer can be found in the documentation to your shell's builtin funcitons, man builtins:

  echo [-neE] [arg ...]
          Output the args, separated by spaces, followed by a newline.
          The return status is 0 unless a write error occurs.  If -n
          is specified, the trailing newline is suppressed.

So, echo -n does the trick. In fact, you will need to use echo -ne, because without -e, your file ends up containing the literal string

me \n you \n him \n

(with the "backslash n" in there!!)

I can't use echo -n because it removes all new lines.

No, it doesn't do that.


Edit: The following dialogue of commands and their output, when running in bash confirm the statements above:

$ Content='me \n you \n him \n'
$ echo $Content > Names.txt
$ cat Names.txt 
me \n you \n him \n
$ echo -e "$Content" > Names.txt 
$ cat Names.txt 
me 
 you 
 him 

$ echo -en "$Content" > Names.txt
$ cat Names.txt 
me 
 you 
 him 
$ 
3
  • 1
    "No, it doesn't do that." in fact it does, because in his own shell the '\n' are expanded as soon as parsed in $Contents opposite to yours or mine where ' \n' are expanded only when echo -e Jul 1 at 8:41
  • how so, the shell is bash, according to tags, and '\n' in bash remains unexpanded (or so I thought!) Jul 1 at 8:53
  • I agree, either the exposed code is not as really executed, or bash does something unexpected, or there is some settings, but all what is reported denote actual newlines in the variable value, not \n. The fact echo -e were unneeded, the fact newlines were removed ... Jul 1 at 9:03
6

Using printf with %b format:

%b ARGUMENT as a string with '' escapes interpreted, except that octal escapes are of the form \0 or \0NNN

$ Content='me \n you \n him \n'
$ printf "%b" "$Content" > Names.txt 
$ cat Names.txt 
me 
 you 
 him
3

Quoting and using printf instead of echo might be the best habits.

First, your description doesn't match. If you have a variable with 'me \n you \n him \n' then it will not have a newline anywhere, not with echo $var, nor printf '%s' $var, nor with echo "$var" or printf '%s' "$var"

$ var='me \n you \n him \n'
$ echo $var
me \n you \n him \n

No newline, no ending newline (other than the one added by echo).

I believe that what you have is something with newlines inside which you have represented by \n. Something like:

$ var=$'me \n you \n him \n'
$ printf '%s' "$var"
me 
 you 
 him
$

And here the quoting is (very) important:

$ printf '%s' $var
meyouhim$ 

.........

$ echo $var
meyouhim
$

.........

$ echo "$var"
me 
 you 
 him 

$

.....

Note the additional newline introduced by echo? That is th eonly one removed with echo -n:

$ echo -n "$var"
me 
 you 
 him 
$

That seems to be the problem with your file, it ends on two newline characters, one from the actual $Content var and one from echo.

If that is actually the problem, then, a echo -n "$var" > Names.txt would give you a file with only one ending newline.

Or much better, do:

$ Content=$'me \n you \n him \n' 
$ printf '%s' "$Content" > Names.txt
$ cat Names.txt 
me 
 you 
 him
$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.