Re: Nice easy sed question

From: Bob Proulx <bob_at_proulx.com>
Date: Fri, 12 Sep 2025 06:04:25 UTC
Frank Leonhardt wrote:
> I've got a file called example.txt:
>
> Line 1
> Line 2
> Line 3
>
> I'm trying to add "New Line" after "Line 2"

Okay.

> Both of these should work as far as I know:
>
> sed  -i.bak  '/Line 2/a\New Line' example.txt

That \N is not valid syntax.

> sed  -i.bak  -e '/Line 2/a\" -e "New Line' example.txt

That \" is not valid syntax.

> (BSD requires a backup specification for -i IIRC, or '')

Yes.  An annoying choice!  Perl pioneered the syntax and being first
at doing so and it being adequate everyone else should have followed
for consistency.

> If I run it with the -i and have a genuine newline after \ it does write the
> correct stuff to stdout:
>
> # sed  '/Line 2/a\
> > New Line' example.txt
> Line 1
> Line 2
> New Line
> Line 3

Yes.  The \ must be followed by a newline.  You have the correct syntax.

> With an -i in any variations of the first two (single command or two -e -e)
> I just get errors like:
>
> ": invalid command code e
> ": extra characters at the end of N command
> ": extra characters after \ at the end of a command
>
> (All starting with " - why?)

Works for me.  Here is an example.

    rwp@mayhem:~$ sed -i.bak '/Line 2/a\
    New Line' foo1
    rwp@mayhem:~$ cat foo1
    Line 1
    Line 2
    New Line
    Line 3

And with use of -e for two different expressions works too.

    rwp@mayhem:~$ sed -i.bak -e '/^Line 2/a\
    New Line' -e 's/3/4/' foo1
    rwp@mayhem:~$ cat foo1
    Line 1
    Line 2
    New Line
    Line 4

What is the exact command you are having trouble with?

> The only way I can make it work is with -i.bak and on two lines (as above).

The newline after the \ backslash is required.  That is the correct syntax.

> The Fine Manual says of 'a':
>
>   [1addr]a\
>      text    Write text to standard output immediately before each attempt to
>              read a line of input, whether by executing the ā€œNā€ function or by
>              beginning a new cycle.

The manual was written by people who already knew how it worked.  The
newline after the backslash is as far as I know always required.  The
behavior is based upon the ed feature.

    man ed
     (.)a    Append text to the buffer after the addressed line.  Text is
             entered in input mode.  The current address is set to last line
             entered.

Here is an ed example.

    rwp@mayhem:~$ ed -s foo1 <<EOF
    /^Line 2/a
    New line
    .
    w
    q
    EOF
    rwp@mayhem:~$ cat foo1
    Line 1
    Line 2
    New line
    Line 3

> This implies the newline is required but I'm struggling with finding a sane
> syntax here. A pointer to some better documentation would be welcome!

This confuses me because you have a working example using sed and it works.

> Or is there a better utility for editing (non-system) configuration files by
> script I just don't know about?

That depends upon many things.  What file is being edited?  Is it an
INI file?  A CSV?  Would a tool like Puppet, Chef, Salt, Ansible be
better?  Perl is powerful and a good general purpose batch editing
choice.  Perhaps ed is the best answer.  Any recommendation without
information would just be a guess in the dark.

I personally like sed and most often use sed to automate edit files.
I always use it in combination with grep to look to see if the file
needs to be edited first in order to make the sequence idempotent such
that files are not always being touched if there is no reason to touch
them.  Because having files updated all of the time falsely points
fingers at them when there are problems.

Bob