Skip to content

Instantly share code, notes, and snippets.

@waffle2k
Created April 3, 2012 18:04
Show Gist options
  • Save waffle2k/2294250 to your computer and use it in GitHub Desktop.
Save waffle2k/2294250 to your computer and use it in GitHub Desktop.
Convert CIDR notation to regex
#!/usr/bin/python
''' Not my script, found on the Internet, and rediscovered on my hard drive
'''
import sys
def cidr_to_regex(cidr):
ip, prefix = cidr.split('/')
base = 0
for val in map(int, ip.split('.')):
base = (base << 8) | val
shift = 32 - int(prefix)
start = base >> shift << shift
end = start | (1 << shift) - 1
def regex(lower, upper):
if lower == upper:
return str(lower)
from math import log10
exp = int(log10(upper - lower))
delta = 10 ** exp
if lower == 0 and upper == 255:
return "\d+"
if delta == 1:
val = ""
for a, b in zip(str(lower), str(upper)):
if a == b:
val += str(a)
elif (a, b) == ("0", "9"):
val += '\d'
elif int(b) - int(a) == 1:
val += '[%s%s]' % (a, b)
else:
val += '[%s-%s]' % (a, b)
return val
def gen_classes():
floor_ = lambda x: int(round(x / delta, 0) * delta)
xs = range(floor_(upper) - delta, floor_(lower), -delta)
for x in map(str, xs):
yield '%s%s' % (x[:-exp], r'\d' * exp)
yield regex(lower, floor_(lower) + (delta - 1))
yield regex(floor_(upper), upper)
return '|'.join(gen_classes())
def get_parts():
for x in range(24, -1, -8):
yield regex(start >> x & 255, end >> x & 255)
return '^%s$' % r'\.'.join(get_parts())
for line in sys.stdin.readlines():
print cidr_to_regex( line )
print
@swettk
Copy link

swettk commented Nov 7, 2014

Thanks for rediscovering this, I owe you a beer should we ever meet

@2xyo
Copy link

2xyo commented Nov 18, 2014

Thanks a lot!

Just some bugs:

1.2.3.8/29   -> 1.2.3.8 - 1.2.3.15
regex: 1\.2\.3\.[1-8]

172.1.8.0/22 -> 172.1.8.0 - 172.1.11.255
regex :  172\.1\.[1-8]\.\d+

@toms3t
Copy link

toms3t commented Jan 22, 2015

Hi, total Python noob here. How do I enter the CIDR so that I can test this script?

@vanillaSprinkles
Copy link

are you in linux?

python2 thescript.py
172.1.8.0/22d

d sends an end of file to window/process/ect

@jmscott
Copy link

jmscott commented May 25, 2016

another issue. try cidr 204.16.248.0/22. i'm seeing ^204.16.2[45][8-1].\d+$
on centos and ubuntu, which misses all of 204.16.249.0/24.

@heshed
Copy link

heshed commented Aug 30, 2016

i think this line should be

https://gist.github.com/petermblair/2294250#file-cidr2regex-py-L51

return '(' + '|'.join(gen_classes()) + ')'

@lowell80
Copy link

I suggest checking out this derived version:

https://gist.github.com/tom-knight/1b5e0dcf39062af8910e

I dug down through all the forks and found this one to be the most promising. Hope this saves other people time!

@radu-c
Copy link

radu-c commented Apr 27, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment