IP addresses
Here’s a regular expression that checks if a string is a valid IPv4 or IPv6 address:
^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(:[0-9a-fA-F]{1,4}){1,6}|:(:[0-9a-fA-F]{1,4}){1,7}|::|fe80:(:[0-9a-fA-F]{1,4}){0,4}%[0-9a-zA-Z]+|::(ffff(:0{1,4})?:)?((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9])|((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9]))$
Here’s the same regexp in free-spacing mode with some comments added:
(?x)^( ( [0-9a-fA-F]{1,4} : ){7} [0-9a-fA-F]{1,4} | ( [0-9a-fA-F]{1,4} : ){1,7} : | ( [0-9a-fA-F]{1,4} : ){1,6} : [0-9a-fA-F]{1,4} | ( [0-9a-fA-F]{1,4} : ){1,5} ( : [0-9a-fA-F]{1,4} ){1,2} | ( [0-9a-fA-F]{1,4} : ){1,4} ( : [0-9a-fA-F]{1,4} ){1,3} | ( [0-9a-fA-F]{1,4} : ){1,3} ( : [0-9a-fA-F]{1,4} ){1,4} | ( [0-9a-fA-F]{1,4} : ){1,2} ( : [0-9a-fA-F]{1,4} ){1,5} | [0-9a-fA-F]{1,4} : ( : [0-9a-fA-F]{1,4} ){1,6} | : ( : [0-9a-fA-F]{1,4} ){1,7} | :: | fe80: ( : [0-9a-fA-F]{1,4} ){0,4} % [0-9a-zA-Z]+ # link-local IPv6 addresses with zone index | :: ( ffff ( : 0{1,4} )? : )? ( ( 25[0-5] | ( 2[0-4] | 1?[0-9] )? [0-9] ) \.){3} ( 25[0-5] | ( 2[0-4] | 1?[0-9] )? [0-9] ) # IPv4-mapped IPv6 addresses and IPv4-translated addresses | ( [0-9a-fA-F]{1,4} : ){1,4} : ( ( 25[0-5] | ( 2[0-4] | 1?[0-9] )? [0-9] ) \.){3} ( 25[0-5] | ( 2[0-4] | 1?[0-9] )? [0-9] ) # IPv4-Embedded IPv6 Address | ( ( 25[0-5] | ( 2[0-4] | 1?[0-9] )? [0-9] ) \.){3} ( 25[0-5] | ( 2[0-4] | 1?[0-9] )? [0-9] ) # IPv4)$
And the equivalent Pomsky expression:
# segment in an IPv4 addresslet num_v4 = range '0'-'255';
# segment in an IPv6 addresslet num_v6 = [ascii_xdigit]{1,4};
# IPv4 addresslet ipv4 = (num_v4 '.'){3} num_v4;
# link-local IPv6 address with zone index# e.g. fe80::7:8%eth0 fe80::7:8%1let link_local = 'fe80:' (':' num_v6){0,4} '%' [ascii_alnum]+;
# IPv4-Embedded IPv6 Address# e.g. 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33let ipv4_embedded = (num_v6 ':'){1,4} ':' ipv4;
# IPv4-mapped IPv6 address or IPv4-translated address# e.g. ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255let ipv4_mapped_translated = '::' ('ffff' (':' '0'{1,4})? ':')? ipv4;
# IPv6 addresslet ipv6 = ( | (num_v6 ':'){7} num_v6 | (num_v6 ':'){1,7} ':' | (num_v6 ':'){1,6} (':' num_v6) | (num_v6 ':'){1,5} (':' num_v6){1,2} | (num_v6 ':'){1,4} (':' num_v6){1,3} | (num_v6 ':'){1,3} (':' num_v6){1,4} | (num_v6 ':'){1,2} (':' num_v6){1,5} | (num_v6 ':') (':' num_v6){1,6} | ':' (':' num_v6){1,7} | '::' | link_local | ipv4_mapped_translated | ipv4_embedded);
# IP address^ (ipv6 | ipv4) $