1

I have a bash script that needs to modify .ssh/config. My goal is to change the HostName value of server1 using sed and I have already managed to do it, but in the file there are more HostName and sed modifies them all. I have tried specifying to sed to stop at the first occurrence but continues to modify them all.

This is the file where I need to change the HostName of server1

Host server1
    HostName 172.160.189.196
    User admin
    Port 353

Host server2
    HostName 254.216.34.18
    User user
    Port 22

This is the command I give:

sed -i '0,/RE/s/HostName .*/HostName 14.208.54.132/' .ssh/config
2
  • What's /RE/ ? Commented Aug 15, 2019 at 14:53
  • 0,/re/ allows the regex to match on the very first line also. In other words: such an address will create a range from the 1st line up to and including the line that matches re - whether re occurs on the 1st line or on any subsequent line. Commented Aug 15, 2019 at 14:58

4 Answers 4

3

Try using a sed range:

sed -i '/Host server1/,/HostName/ s/HostName .*/HostName 14.208.54.132/' .ssh/config

This will replace HostName in the range of lines between Host server1 and the first occurrence of HostName, which I think is what you want.

Sign up to request clarification or add additional context in comments.

1 Comment

I've tried all three answers and they work, but I choose this for the simple reason that it uses sed and has a rather simple syntax.
0

While awk is generally known to work on lines, it actually works with records, by default lines. A record can be defined by a record separator RS. If this variable is empty, it assumes that a record is given by text-blocks separated by one or more empty lines. With this you can do the following:

awk 'BEGIN{RS="";FS=OFS="\n";ORS="\n\n"}
     ($1~/server1/) {sub(/Hostname[^\n]*\n/,"Hostname 14.208.54.132" OFS)}
     1' file

This is not short, but conceptually clean. Obviously, you have to update the regex to match the hostname such that it is unique. If you also have a hostname server1a, then you will have to make sure that ($1~/server1/) does not match that.

Comments

0

You can use awk like this:

awk '$2=="server1" {f=1} f && /HostName/ {$0="    HostName 14.208.54.132";f=0} 1' file
Host server1
    HostName 14.208.54.132
    User admin
    Port 353

Host server2
    HostName 254.216.34.18
    User user
    Port 22

1 Comment

This might fail if you have a line like "User userver1"
0

This might work for you (GNU sed):

sed '/\<server1\>/{:a;n;/HostName/!ba;s/\S\+/14.208.54.132/2}' file

Focus on a line containing server1 then read additional lines until one containing HostName and substitute the second field for the desired result.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.