Using variable in sed

Hi all,

Somescript.sh looks like this:

#!/bin/sh
#  somecript.sh

somecommand1

somecommand2

#End

exit

Now I want to add somecommand3 to somescript.sh above #End

I now how to do this:

sed -ie '/#End/i\
somecommand3\
' /location/of/somescript.sh

This works fine. But now I want to add a variable the same way. I can't get this to work. I thought something like this:

command=somecommand3

sed -ie '/#End/i\
"$command"\
' /location/of/somescript.sh

But this just adds "$command".

Thanks

The shell sees a multi-line 'string' where $command is not seen and substituted.

sed -ie '/#End/i\
"$command"\
' /location/of/somescript.sh

The trick is to have 'string1' $command 'string2', so the $command is seen and substituted by the shell.

sed -ie '/#End/i\
'$command'\
' /location/of/somescript.sh

or

sed -ie '/#End/i\
'"$command"'\
' /location/of/somescript.sh

The latter uses the fact that the shell sees and substitutes $command within a "string".

Not recommended. If command contains a multi-word string, the sed command line will break.

The reason is that inside a single-quoted string double-quoting has no effect. From the POV of the shell, though, you are inside a single-quoted string. This should work:

sed -ie '/#End/i\
'"$command"'\
' /location/of/somescript.sh

Note that the single-quoted string ends, then a double-quoted string starts and when this ends another single-quoted string starts. This may look cumbersome, but it is the only way to ensure the sed-command will not break if "$command" contains whitespace.

I hope this helps.

bakunin

Thanks guys,

I get the point. :b:

Next challenge:

The variable is a multi-line variable:

read -d '' command <<EOF
command3a
command3b
command3c
EOF

Now if I run:

sed -ie '/#End/i\
'"$command"'\
' /location/of/somescript.sh

I get:

sed: 3: "/#End/i\
command3a
command3b ...": invalid command code c

What shell do you use?
Try:

sed -ie '/#End/i\
'"${command//$'\n'/\\$'\n'}"'\
' /location/of/somescript.sh

bash

And it works! Can you please explain how it works because you lost me at the \\//\\ signs... :smiley:

Still don't know exactly HOW it works (would like to), but it works fine! I found out that I can add as many lines to the variable as I want. It will insert all. :slight_smile:

One last question:

At some point the somescript.sh will look like this:

#!/bin/sh
#  somecript.sh

somecommand1

somecommand2
command3a
command3b
command3c
command4a
command4b
command4c
command5a
command5b
command5c
command6a
command6b
command6c
#End

exit

It would be cleaner if there was a white line between every command. I tried to change the variable:

read -d '' command <<EOF
command3a
command3b
command3c

EOF

But it just skips the white line. Is there a trick for this? Or should I change the sed command?

Up!

All I need is one extra line... :slight_smile:

Use the "a" (append) command of sed with line pattern. For example:

sed '/^pattern/ a \
' /path/to/input

will append a newline to every line which starts with "pattern". Notice that the newline character has to be escaped with "\", which is why the line is separated in two in the above.

As an aside: you probably got no answer any more because people thought you could figure that out yourself. This forum is about helping you help yourself, not doing your work for you. Not to know something is one thing, being to lazy another. You might want to think about that.

I hope this helps.

bakunin

Thanks but I can't get it to work within my code. My code looks like this:

sed -ie '/#End/i\
'"${command//$'\n'/\\$'\n'}"'\
' /location/of/somescript.sh

I suggest consulting the sed man page ("man sed") to find out how to put more than one command in a sed script. You could also try a book (the one i liked most is Dale Dougherty, "sed & awk", O'Reilly).

I hope this helps.

bakunin

I wonder how a multi-line $command works at all - because the sed i command wants a \ at the end of each line.

I suggest a while loop, so for each iteration sed runs with a one-line $command which can be empty.

while read command
do
sed -i '/#End/i\
'"$command"'\
' /location/of/somescript.sh
done << EOF
command3a
command3b
command3c

EOF

---------- Post updated at 11:13 AM ---------- Previous update was at 11:10 AM ----------

NB this already inserts an empty line.
Otherwise use

sed -i '/#End/i\
'"$command" /location/of/somescript.sh

If you use GNU sed, you don't need the awkward newline after the i command. So you can write a simpler, easier-to read one-line script.

 sed -i '/#End/ i \thing-to-insert' somescript.sh

Also, to eliminate some confusion, you can write the sed script to an external file, and then use -f to execute the script. That can help make the syntax easier to read, and probably avoid some of the complexity related to quoting / not quoting $command.