10

I have an input file with IPv4 addresses:

94.228.16.0 - 94.228.25.255
94.241.136.0/24
94.241.136.0 - 94.241.136.255
94.29.128.0/17
94.29.128.0 - 94.29.191.0
94.29.192.0 - 94.29.255.0
94.74.181.0/24
94.74.181.0 - 94.74.181.31
94.74.181.128 - 94.74.181.255

How I can convert the address ranges to netmasks? The result should be:

94.228.16.0/21
94.241.136.0/24
94.241.136.0/24
94.29.128.0/17
94.29.128.0/19
94.29.192.0/19
94.74.181.0/24
94.74.181.0/27
94.74.181.128/25
  • 3
    Several of the results you ask for are incorrect, so no valid bash script will produce them. For instance, the first range is not expressible using a netmask: 94.228.16.0/21 gives 94.228.16.0 - 94.228.23.255, and the next wider 94.228.16.0/20 gives 94.228.16.0 - 94.228.31.255. Also, ranges ending in .0 cannot be produced by any netmask. – zwets Jan 31 '17 at 9:28
  • @Zanna you're cheating, the poster asked using bash. My bash has no ipcalc builtin. ;-) – zwets Jan 31 '17 at 9:52
  • @zwets ah I've figured it out! But you're right, the shell needs a lot of help hahaha – Zanna Jan 31 '17 at 10:00
14

First you will need to install a package to do the conversion

sudo apt install ipcalc

Now you can do it with this little script (please note that it doesn't work if you quote the variable):

$ while read line; do if [[ $line = *-* ]]; then (ipcalc $line | sed '2!d'); else echo $line; fi; done < file
94.228.16.0/21
94.241.136.0/24
94.241.136.0/24
94.29.128.0/17
94.29.128.0/19
94.29.192.0/19
94.74.181.0/24
94.74.181.0/27
94.74.181.128/25

or more readably

while read line; do
   if [[ $line = *-* ]]; then 
     (ipcalc $line | sed '2!d')
   else echo $line
   fi
done < file
  • @Oleksii always a pleasure :) – Zanna Feb 3 '17 at 8:19
3

Perhaps not surprisingly, there is a CPAN perl module Net::CIDR for this.

So for example:

$ perl -MNet::CIDR=range2cidr -lne 'print for range2cidr $_' yourfile
94.228.16.0/21
94.228.24.0/23
94.241.136.0/24
94.241.136.0/24
94.29.128.0/17
94.29.191.0/32
94.29.128.0/19
94.29.160.0/20
94.29.176.0/21
94.29.184.0/22
94.29.188.0/23
94.29.190.0/24
94.29.255.0/32
94.29.192.0/19
94.29.224.0/20
94.29.240.0/21
94.29.248.0/22
94.29.252.0/23
94.29.254.0/24
94.74.181.0/24
94.74.181.0/27
94.74.181.128/25

The module is available on Ubuntu by installing the libnet-cidr-perl package.

NB I have not validated your input or the results.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.