1

I am wondering how Bash can solve the next exercise. I have a set of config files in one directory where some IP addresses pointed out. E.g:

conf1.txt:

ip-addr: 192.168.1.2;
mask...;
gateway...;
another ip-addr: 192.168.1.5;
one more ip-addr: 192.168.1.10;
... 

conf2.txt:

ip-addr: 192.168.1.2;
mask...;
gateway...;
another ip-addr: 192.168.1.5;
one more ip-addr: 192.168.1.10;
...

And the question is: How can I change all IP addresses with another pool of IP addresses (192.168.1.100-192.168.1.254) but in all files. So for example:

  • 192.168.1.2 -> 192.168.1.100
  • 192.168.1.5 -> 192.168.1.101
  • 192.168.1.10 ->192.168.1.102

I suppose that there is some mechanism of assigning values from one array to another because hardcoded version like:

 sed "s/192.168.1.2/192.168.1.100/g"; 

Isn't good.

Biffen
  • 5,354
  • 5
  • 27
  • 32
Vlad
  • 769
  • 15
  • 32
  • 2
    Are you looking for a solution using bash + standard shell tools or would you be willing to consider using a more powerful language such as Perl? – Tom Fenech Oct 02 '15 at 13:29
  • I'mnot bash guru, but I would do next: read from file http://stackoverflow.com/questions/10929453/bash-scripting-read-file-line-by-line and then split each line http://stackoverflow.com/questions/918886/how-do-i-split-a-string-on-a-delimiter-in-bash and replace with sed at the end. – Serge P Oct 02 '15 at 13:36
  • I prefer to use bash script + shell tools – Vlad Oct 02 '15 at 13:38
  • 2
    In what kind of format do you have the mapping? Or do you just want to extract the IPs, and create new ones on the fly? – choroba Oct 02 '15 at 13:39
  • I just have to use a new pull (order doesn't matter but all existent ip adresses should have the same new values within all files) and store results in this configs replacing old values. – Vlad Oct 02 '15 at 13:46

3 Answers3

2

Perhaps slightly verbose, but it should do. First, a list of substitution commands is assembled into a temporary file and then sed is executed in order to perform those substitutions.

cmds=$(mktemp)
while read line
do
    printf "s/%s/%s/g\n" $line >> $cmds
done < ip_table

sed -f $cmds input > output
rm -f $cmds

Here, the IP transformation table is assumed to be stored in a 2-column file ip_table

192.168.1.2 192.168.1.100
192.168.1.5 192.168.1.101

Although note that this approach meets its demise should the IP translation table look like

192.168.1.2 192.168.1.100
192.168.1.100 192.168.1.5

because then 192.168.1.2 gets replaced with 192.168.1.5.

ewcz
  • 11,464
  • 1
  • 19
  • 42
1

Do you want to auto-generate the new IPs? If so, here's one way to do it:

conf_files=config*.txt
pre=192.168.1.
suf=100

grep -hoP '([0-9]{1,3}\.){3}[0-9]{1,3}' $conf_files |
sort -u |
while read ip; do
    if (( suf > 254 )); then
        print "Error: Oops! Suffix is more than 254" >&2
        exit 1
    fi
    sed -i "s:$ip:$pre$suf:g" $conf_files
    ((suf++))
done

Here's how it works:

  1. Extract all the IP address from the config files
  2. Sort them and remove duplicates
  3. In the while loop, calculate the new IP and
  4. use sed to replace the old IPs
svsd
  • 1,681
  • 7
  • 14
1

A hardcoded sed script is not nice. Fortunately, you can create a sed script dynamically.

grep -ho '192\.168\.1\.[0-9]\+' conf*.txt \
    | sort | uniq | nl -v100 \
    | sed 's/\./\\./g;s/ *\(.*\)\t\(.*\)/s=\2=192.168.\1=g/' | LC_ALL=C sort \
    | sed -f- conf*.txt

The first line extracts all IP addresses (note there're other means how to express them).

The second line throws out duplicates and number the lines starting from 100.

The third line changes each IP address preceded by a number into a sed command. The commands are then sorted so that 0.0.0.100 gets replaced before 0.0.0.10.

The last line runs the generated script on the input files.

Bugs: doesn't check whether the number of lines < 157.

choroba
  • 200,498
  • 20
  • 180
  • 248