How do I add a line of text to the middle of a file using bash?

awk, bash, grep, linux, sed

Solution

Here is a solution using sed:

$ sed -n 'H;${x;s/^\n//;s/nameserver .*$/nameserver 127.0.0.1\n&/;p;}' resolv.conf

# Generated by NetworkManager
domain dhcp.example.com
search dhcp.example.com
nameserver 127.0.0.1
nameserver 10.0.0.1
nameserver 10.0.0.2
nameserver 10.0.0.3

How it works: first, suppress the output of sed with the `-n` flag. Then, for each line, we append the line to the hold space, separating them with newlines:

H

When we come to the end of the file (addressed by `$`) we move the content of the hold space to the pattern space:

x

If the first line in pattern space is blank we replace it with nothing.

s/^\n//

Then we replace the first line starting with `nameserver` by a line containing `nameserver 127.0.0.1`, a new line (Your version of `sed` may not support `\n`, in which case replace the `n` with a literal newline) and the original line (represented by `&`):

s/nameserver .*$/nameserver 127.0.0.1\n&/

Now we just need to print the results:

p

Problem

I'm trying to add a line of text to the middle of a text file in a bash script. Specifically I'm trying add a nameserver to my /etc/resolv.conf file. As it stands, resolv.conf looks like this: ``` # Generated by NetworkManager domain dhcp.example.com search dhcp.example.com nameserver 10.0.0.1 nameserver 10.0.0.2 nameserver 10.0.0.3 ``` My goal is to add `nameserver 127.0.0.1` above all other nameserver lines, but below any text above that. In the end I want to my resolve.conf file to look like this: ``` # Generated by NetworkManager domain dhcp.example.com search dhcp.example.com nameserver 127.0.0.1 nameserver 10.0.0.1 nameserver 10.0.0.2 nameserver 10.0.0.3 ``` How is this possible via a bash script? Is this something sed or awk can do? Or would creative greping to recreate the file be my best move?

Original source

Related problems