glux
glux

Reputation: 532

Add string between two patterns - sed

I'm looking to build a startup script that will add a string of text between two patterns.

8.34.217.13 cds.rhel.updates.googlecloud.com
10.128.0.2 instance-1.c.testenvio1.internal instance-1 **want to add string here** # Added by Google
169.254.169.254 metadata.google.internal  # Added by Google

I want it to look like this:

8.34.217.13 cds.rhel.updates.googlecloud.com
10.128.0.2 instance-1.c.testenvio1.internal instance-1 104.197.247.254 instance1.com  # Added by Google
169.254.169.254 metadata.google.internal  # Added by Google

I'm using the following sed command but it inserts my string when it encounters the first "instance-1"

sed -i 's/\<instance-1\>/& 104.197.247.254 instance1.com/' /etc/hosts


8.34.217.13 cds.rhel.updates.googlecloud.com
10.128.0.2 instance-1 104.197.247.254 instance1.com.c.testenvio1.internal instance-1  # Added by Google
169.254.169.254 metadata.google.internal  # Added by Google

Upvotes: 3

Views: 2650

Answers (3)

iamauser
iamauser

Reputation: 11469

Include the whitespace after instance-1 which distinguishes it from the first occurrence:

$ sed -i 's/instance-1 /&104.197.247.254 instance1.com /g' inputFile

OR

if you know it is always the second occurrence, then use, /2 to replace it,

$ sed -i 's/instance-1/& 104.197.247.254 instance1.com /2' inputFile

For future reference, if you want to add a string between two patterns

$ sed '/pattern1/,/pattern2/s//& INSERT THIS TEXT/g' inputFile

For this example, it would look like,

# You still need that whitespace to distinguish the second occurrence from first:
$ sed '/instance-1 /,/# Added/s//&104.197.247.254 instance1.com /g' inputFile

Upvotes: 0

sjsam
sjsam

Reputation: 21955

Perhaps some insight about where the data is coming from is certainly helpful here.

The # Added by Google suggests that those lines contain information about Google Compute Engine instances. More importantly, they are lines added by Google and fortunately follows a predefined pattern.

In that case, something like below would help

$ sed -Ei -- 's/([[:blank:]]+instance-1[[:blank:]]+)(#.*)$/\1 104.197.247.254 instance1.com \2/' /etc/hosts

Output

8.34.217.13 cds.rhel.updates.googlecloud.com
10.128.0.2-instance-1-c.testenvio1.internal instance-1   104.197.247.254 instance1.com # Added by Google
169.254.169.254 metadata.google.internal  # Added by Google

Sidenote: The actual number of spaces are preserved too.

Upvotes: 1

HardcoreHenry
HardcoreHenry

Reputation: 6377

Try this:

sed -i 's/^\([0-9.]* [^ ]* \<instance-1\>\)/\1 104.197.247.254 instance1.com/' /etc/hosts

This expression will read the first two fields, and then try to match instance-1 in the third field only (this assumes that the fields are seperated by a single space delimiter -- you can adjust the regex if that's not the case...)

The \( and \) indicate that sed should store the matched text in variable \1. The ^ forces it to only match from the beginning of the line. The rest is pretty straight forward

Upvotes: 0

Related Questions