2

I am trying to using sed -i command to insert a string variable in the 1st line of a text file. This command work : sed -i '1st header' file.txt But when i pass a variable this doesn't work. example :

var=$(cat <<-END
    This is line one.
    This is line two.
    This is line three.
END
)

sed -i '1i $var' file.txt # doesn't work
sed -i ’1i $var’ file.txt # doesn't work

Any help with this problem

Thank you

Sami
  • 25
  • 1
  • 3
  • Why didn't you try `"1i $var"`? And how did you get those other strange thingies that look like reverse backticks anyway... – Andrey Tyukin Mar 09 '18 at 20:49

3 Answers3

6

First, let's define your variable a simpler way:

$ var="This is line one.
This is line two.
This is line three."

Since sed is not good at working with variables, let's use awk. This will place your variable at the beginning of a file:

awk -v x="$var" 'NR==1{print x} 1' file.txt

How it works

  • -v x="$var"

    This defines an awk variable x to have the value of shell variable $var.

  • NR==1{print x}

    At the first line, this tells awk to insert the value of variable x.

  • 1

    This is awk's shorthand for print-the-line.

Example

Let's define your variable:

$ var="This is line one.
> This is line two.
> This is line three."

Let's work on this test file:

$ cat File
1
2

This is what the awk command produces:

$ awk -v x="$var" 'NR==1{print x} 1' File
This is line one.
This is line two.
This is line three.
1
2

Changing a file in-place

To change file.txt in place using a recent GNU awk:

awk -i inplace -v x="$var" 'NR==1{print x} 1' file.txt

On macOS, BSD or older GNU/Linux, use:

awk -v x="$var" 'NR==1{print x} 1' file.txt >tmp && mv tmp file.txt
John1024
  • 109,961
  • 14
  • 137
  • 171
  • doesn't work, no thing happen when tested in a script – Sami Mar 09 '18 at 22:57
  • @Sami It worked fine for me. I just tested it again and added the results to the answer as an example. If it works differently for you, please provide details. – John1024 Mar 09 '18 at 23:44
  • Thanks John. but the change inplace does'nt work. – Sami Mar 12 '18 at 15:56
  • _"change inplace does'nt work"_ What does that mean? Which of the two change-in-place commands were you using? Which OS are you on? In what way did it not work? Was there an error message? What did it say? – John1024 Mar 12 '18 at 16:02
  • This command : awk -i inplace -v x="$var" 'NR==1{print x} 1' file.txt – Sami Mar 12 '18 at 16:05
  • awk -i inplace -v x="$var" 'NR==1{print x} 1' file.txt Usage: awk [POSIX or GNU style options] -f progfile [--] file ... Usage: awk [POSIX or GNU style options] [--] 'program' file ... POSIX options: GNU long options: -f progfile --file=progfile -F fs --field-separator=fs -v var=val --assign=var=val -m[fr] val -O --optimize -W compat --compat – Sami Mar 12 '18 at 16:06
  • @Sami What OS are you on? What version does `awk --version` show? – John1024 Mar 12 '18 at 16:10
  • @Sami Also, if it turns out that your version of awk is too old to support `-i inplace`, then try the macOS BSD version. – John1024 Mar 12 '18 at 16:11
  • awk --version GNU Awk 3.1.7 Copyright (C) 1989, 1991-2009 Free Software Foundation. is it old ? – Sami Mar 12 '18 at 16:13
  • @Sami Yes, that is old. 3.1.7 was [released nearly a decade ago](https://groups.google.com/forum/#!topic/comp.lang.awk/lBxgDQlh17Y). Try the command in the macOS/BSD version. That should work with old GNU awk as well. – John1024 Mar 12 '18 at 16:17
  • i don't have macOS/BSD, i am with unbuntu 14 – Sami Mar 12 '18 at 16:21
  • @Sami On an old Ubuntu, please try `awk -v x="$var" 'NR==1{print x} 1' file.txt >tmp && mv tmp file.txt` – John1024 Mar 12 '18 at 21:25
0

Using printf...

$ var="This is line one.
This is line two.
This is line three.
"

Use cat - to read from stdin and then print into a new file. Move it to the original file if you want to modify it.

$ printf "$var" | cat - file > newfile && mv newfile file;
iamauser
  • 11,119
  • 5
  • 34
  • 52
0

Not the best job for sed. What about a simple cat ?

cat - file.txt <<EOF > newfile.txt
This is line one.
This is line two.
This is line three.
EOF

# you can add mv, if you really want the original file gone
mv newfile.txt file.txt

And for the original problem - sed does not like newlines and spaces in it's 'program', you need to quote and escape the line breaks:

# this works
sed $'1i "abc\\\ncde"' file.txt

# this does not, executes the `c` command from the second line
sed $'1i "abc\ncde"' file.txt
liborm
  • 2,634
  • 20
  • 32