1

I am trying to add multiple lines to a file, all with a leading a tab. The lines should be inserted on the first line after matching a string.

Assume a file with only one line, called "my-file.txt" as follows:

foo

I have tried the following sed command:

sed "/^foo\$/a \tinsert1\n\tinsert2" my-file.txt

This produces the following output:

foo
tinsert1
    insert2

Notice how the the tab that should be on the first (inserted) line is omitted. Instead it prints an extra leading 't'.

Why? And how can I change my command to print the tab on the first line, as expected?

unique_ptr
  • 233
  • 3
  • 9

2 Answers2

1

With GNU sed:

sed '/^foo$/a \\tinsert1\n\tinsert2' file
     <---- single quotes!      --->

Produces:

foo
    insert1
    insert2

From the manual:

  a \

  text   Append text, which has each embedded newline preceded by a backslash.

Since the text to be append itself has to to be preceded by a backslash, it needs to be \\t at the beginning.


PS: If you need to use double quotes around the sed command because you want to inject shell variables, you need to escape the \ which precedes the text to be appended:

ins1="foo"
ins2="bar"
sed "/^foo\$/a \\\t${ins1}\n\t${ins2}" file
hek2mgl
  • 152,036
  • 28
  • 249
  • 266
  • 1
    Yes, that is why I needed the double quotes. I had tried \\t but did'nt think of \\\t :) – unique_ptr Aug 17 '19 at 13:02
  • @unique_ptr since GNU(!) sed interprets the `\t` and `\n` itself, the following would also work: `sed "/^foo\$/a \\\\t${ins1}\\n\\t${ins2}" file` :) – hek2mgl Aug 17 '19 at 13:45
1

sed is for doing s/old/new on individual strings, that is all. Just use awk:

$ awk '{print} $0=="foo"{print "\tinsert1\n\tinsert2"}' file
foo
        insert1
        insert2

The above will work using any awk in any shell on every UNIX box and is trivial to modify to do anything else you might want to do in future.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185