Solved Correct syntax for the 'a' function of FreeBSD's sed?

quamenzullo

Active Member

Reaction score: 21
Messages: 162

I'd liked to use the 'a' function of sed to append something after a given line in a file.
For instance, I want to add "ListenAddress xx.xx.xxx.xxx" after the line that begins with "#ListenAddress" in a copy of sshd_config:
Using sh I do:
Rich (BB code):
# IP=xx.xx.xxx.xxx
# sed -E -i "" "/^#ListenAddress.*/aListenAddress $IP" new/sshd_config
sed: 1: "/^#ListenAddress.*/aLis ...": command a expects \ followed by text

Fine, as sed(1) reads:
[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.

But then:

Code:
# sed -E -i "" "/^#ListenAddress.*/a\ListenAddress $IP" new/sshd_config
sed: 1: "/^#ListenAddress.*/a\Li ...": extra characters after \ at the end of a command

Other incorrect variations:

Code:
# sed -E -i "" "/^#ListenAddress.*/a\
> ListenAddress $IP" new/sshd_config
sed: 1: "/^#ListenAddress.*/aLis ...": command a expects \ followed by text

# sed -E -i "" "/^#ListenAddress.*/a\\ListenAddress $IP" new/sshd_config
sed: 1: "/^#ListenAddress.*/a\Li ...": extra characters after \ at the end of a command

# sed -E -i "" "/^#ListenAddress.*/a\\\
> ListenAddress $IP" new/sshd_config
sed: 1: "/^#ListenAddress.*/a\Li ...": extra characters after \ at the end of a command
 
OP
quamenzullo

quamenzullo

Active Member

Reaction score: 21
Messages: 162

Shouldn't that '-E' be '-e'....
No, this is to use regular expressions. '-e' is something else.
From sed(1):
-E Interpret regular expressions as extended (modern) regular ex-
pressions rather than basic regular expressions (BRE's). The
re_format(7) manual page fully describes both formats.
-e command
Append the editing commands specified by the command argument to
the list of commands.
 
OP
quamenzullo

quamenzullo

Active Member

Reaction score: 21
Messages: 162

Finally, this is not completely correct. See this post.

Well, after searching further, I found out that a solution is to use both '-e' and '-E':
Code:
# sed -E -i "" -e "/^#ListenAddress.*/a\\
> ListenAddress $IP" new/sshd_config
# grep xx new/sshd_config
ListenAddress xx.xx.xxx.xxx
#

What I don't understand is how, from the manual, it would have been possible to understand that. Moreover, the addition of several lines from another text file (command 'r') does not require to use '-e', for instance this is correct: sed -E -i "" "/pattern/r input_lines.txt" dest.txt
 
Last edited:
OP
quamenzullo

quamenzullo

Active Member

Reaction score: 21
Messages: 162

If you think the documentation can be improved, you can report it as a bug here.
OK, but before reporting a bug, I'd liked to ensure I have understood everything and not missed anything.
I read that:
Multiple commands may be specified by using the -e
But I do not understand how this: sed -E -i "" -e "/^#ListenAddress.*/a\\ > ListenAddress $IP" new/sshd_config
contains more than one command, while this: sed -E -i "" "/pattern/r input_lines.txt" dest.txt contains only one command.
In both cases I see only one command (the function of the command being a in the first case, r in the second case).
 

balanga

Son of Beastie

Reaction score: 217
Messages: 4,024

Well, after searching further, I found out that a solution is to use both '-e' and '-E':
Code:
# sed -E -i "" -e "/^#ListenAddress.*/a\\
> ListenAddress $IP" new/sshd_config
# grep xx new/sshd_config
ListenAddress xx.xx.xxx.xxx
#

What I don't understand is how, from the manual, it would have been possible to understand that. Moreover, the addition of several lines from another text file (command 'r') does not require to use '-e', for instance this is correct: sed -E -i "" "/pattern/r input_lines.txt" dest.txt
I'm intrigued as to how you discovered the '-E' option. I don't see it in sed. Neither do I see the '-i' option. This option is different to other (GNU) versions of sed and it's worth mentioning for anyone wishing to make inline changes to a file and can't get the syntax right.

Just noticed that when I do a web search for 'freebsd man' the top three hits point to different FreeBSD pages all of them showing different options for sed. Never noticed before, but just to make a note to self.... check that page comes from 'man.freebsd.org'...
 
OP
quamenzullo

quamenzullo

Active Member

Reaction score: 21
Messages: 162

balanga Well I got it from there: sed(1)
Your link is the sed man for the Unix 7th Edition, released in 1979. Quite not sure this is still relevant for FreeBSD 12.2.

The -i requires a suffix, that's the reason for the "" following it (no suffix, i.e. no backup). That's indeed different from the GNU version.
 
OP
quamenzullo

quamenzullo

Active Member

Reaction score: 21
Messages: 162

Solution
Well I have included several changes in the same time in my previous attempts. -e is not required at all.

This works too:
# sed -E -i "" "/^#ListenAddress.*/a\\ > ListenAddress $IP" new/sshd_config
But no newline is inserted after the text being inserted here.

If one want to have it on a single line, this is OK:
# sed -E -i "" "/^#ListenAddress.*/a\\ > ListenAddress $IP " new/sshd_config

And strangely, this gives the same result (adding -e inserts a newline, maybe because sed expects then another command??):
# sed -E -i "" -e "/^#ListenAddress.*/a\\ > ListenAddress $IP" new/sshd_config
 
Top