Search code examples
regexlinuxsedterminalgnu

GNU sed matching lines with unescaped characters


I'm running into an issue with SED and it's not quite behaving the way I'd expect it. I'm attempting to append to lines (using lines breaks, \n) after a match. I'm attempting to auto-fix a Service file for all our deployed machines, and all future ones (well, until the vendor fixes it).

Suppose I have a file called "foo.service" which looks like this:

[Unit]
Description=Foo
After=network.target

[Service]
User=UserFoo
Environment="SERVICENAME=foo"
Environment="SERVICEPATH=/opt/foo"
Environment="SERVICEMAINCLASS=com.GoogleFoo.service.foo.ServiceRunner

I need to match sed to "[Service]". I cannot match to "Service" otherwise it will write the output multiple times (it'll match to the line: [Service] and the line "Environment="SERVICEMAINCLASS=com.GoogleFoo.service.foo.ServiceRunner"". I built a much simpler file to work on expressions to see where it's going wrong, the best I can find are the brackets are an unescaped character.

I've tried two commands which give different results. (Results -> Imgur Link)

sed -i "/[abc]/aRestart=on-failure\nRestartSec=60" TestFile && cat TestFile
sed -i "/abc/aRestart=on-failure\nRestartSec=60" TestFile.bak && cat TestFile.bak

Where testFile and TestFile.bak are the same file

[abc]
cde
efg
ghi

Where am I going wrong with the commands? I've tried encasing the patterns in various quotes and other escape characters, but it's not worked to date. Any input?

Cheers, Mike


Solution

  • With this -:

    sed 's/^\[Service\]/&\nRestart=on-failure\nRestartSec=60/' foo.service
    

     Output

    [Unit]
    Description=Foo
    After=network.target
    
    [Service]
    Restart=on-failure
    RestartSec=60
    User=UserFoo
    [...]
    

     Explanations

    • you need to escape square brackets, because sed treat these as a class of characters
    • & is what matched in the substitution