14

I'm learning about sed but it is very difficult to me understand it.

I have adsl with dynamic ip so and i want to put current ip on hosts file.

This following script just tells me the current wan ip address and no more:

IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
echo $IP

The result:

192.42.7.73

So, i have a line on hosts file with the old ip address:

190.42.44.22   peep.strudel.com

and i want to update host file like this:

192.42.7.73    peep.strudel.com

How can i do it? I think i can use the hostname as pattern...

The reason of doing this is because my server is a client of my router, so it access the internet thru its gateway and not directly. And postfix always is logging me that "connect from unknown [x.x.x.x]" (where x.x.x.x is my wan ip!) and it can't resolve that ip. I think that maybe if i specify this relating with my fqdn host/domain, on hosts file it will works better.

Thanks Sergio.

sergius
  • 165
  • 1
  • 1
  • 11

3 Answers3

19

You can use a simple shell script:

#! /bin/bash

IP=$(dig +short myip.opendns.com @resolver1.opendns.com)

HOST="peep.strudel.com"

sed -i "/$HOST/ s/.*/$IP\t$HOST/g" /etc/hosts

Explanation:

sed -i "/$HOST/ s/.*/$IP\t$HOST/g" /etc/hosts means in the line which contains $HOST replace everything .* by $IP tab $HOST.

Tiago Lopo
  • 7,619
  • 1
  • 30
  • 51
  • thanks Tiago, i like your solution, very simple and clear to understand. – sergius Feb 12 '15 at 11:05
  • One thing i found is `dig` always returns a zero exit code so could mess up your hosts file. Excellent use of `sed` should have been accepted answer. – Zlemini Sep 27 '18 at 19:01
6

using sed

sed -r "s/^ *[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+( +peep.strudel.com)/$IP\1/"

. [0-9]+\. find all lines that matches 1 or more digits with this pattern 4 consecutive times then pattern peep.strudel.com .The parenthesis around the pattern peep.strudel.com save it as \1 then replace the whole patten with your variable and your new ip.

another approach:instead of saving pattern to a variable named IP, you can execute your command line inside sed command line to get the new IP .

   sed -r "s/^ *[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+( +peep.strudel.com)/$(dig +short myip.opendns.com @resolver1.opendns.com)\1/"

using gawk

gawk -v IP=$IP '/ *[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+( +peep.strudel.com).*/{print gensub(/ *[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+( +peep.strudel.com)/,IP"\\1","g")}'
repzero
  • 8,254
  • 2
  • 18
  • 40
  • thanks, i used your second example (all in 1 command line), added -i parameter to sed for saving the file, as Avinash Raj and Tiago suggested. It works :) (note: i added more spaces before ( +peep.strudel.com), matching the editing of original post) – sergius Feb 12 '15 at 11:03
  • great! :D.I catered for the spaces in my command line using this piece of code " +" after peep.strudel.com – repzero Feb 12 '15 at 11:06
  • I +1 this question so that you can reach 15 rep to vote! – repzero Feb 12 '15 at 11:09
3

You need to include the sed code inside double quotes so that the used variable got expanded.

sed "s/\b\([0-9]\{1,3\}\.\)\{1,3\}[0-9]\{1,3\}\b/$IP/g" file

Add -i parameter to save the changes made. In basic sed \(..\) called capturing group. \{min,max\} called range quantifier.

Example:

$ IP='192.42.7.73'
$ echo '190.42.44.22   peep.strudel.com' | sed "s/\b\([0-9]\{1,3\}\.\)\{1,3\}[0-9]\{1,3\}\b/$IP/g"
192.42.7.73   peep.strudel.com
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274