0

I have seen the code to compress IPV6 in java. The link specifies the same. Below is the code in Java . String resultString = subjectString.replaceAll("((?::0\\b){2,}):?(?!\\S*\\b\\1:0\\b)(\\S*)", "::$2"); But in Javascript I am confused as how can I get the regex expression to match the same . Can you share some pointers here?

Example : fe80:00:00:00:8e3:a11a:2a49:1148 Result : fe80::8e3:a11a:2a49:1148

karthik339
  • 199
  • 1
  • 6

4 Answers4

4

There's a couple problems with the other answer by @ClasG:

  1. If the repeating zeroes are at the beginning of the IPv6 address or it's all zeroes, only 1 colon is replaced.
  2. If the repeating zeroes are at the end, they're not replaced.

I suggest using the regex \b:?(?:0+:?){2,} and have it replaced with :: (two colons)

Regex101 tests

JavaScript example:

var ips = [
'2001:0db8:ac10:0000:0000:0000:0000:ffff',
'2001:0db8:ac10:0000:0000:0000:0000:0000',
'0:0:0:0:0:2001:0db8:ac10',
'2001:0db8:ac10:aaaa:0000:bbbb:cccc:ffff',
'2001:0db8:ac10:0000:0000:bbbb:00:00' 
];

for (var i = 0; i < ips.length; i++) {
document.write(ips[i].replace(/\b:?(?:0+:?){2,}/, '::') + "<br>"); 
}

Note: The Regex101 tests replace multiple repeating groups of zeroes. In XYZ programming language, you'll have to limit the number of replacements to 1. In JavaScript, you omit the global flag. In PHP, you set the $limit for preg_replace to 1.

SameOldNick
  • 2,397
  • 24
  • 33
3

You can do it by replacing

\b(?:0+:){2,}

with

:

function compIPV6(input) {
  return input.replace(/\b(?:0+:){2,}/, ':');
}

document.write(compIPV6('2001:db8:0:0:0:0:2:1') + '<br/>');
document.write(compIPV6('fe80:00:00:00:8e3:a11a:2a49:1148' + '<br/>'));

Check it out at regex101.

SamWhan
  • 8,296
  • 1
  • 18
  • 45
2

You can use a function that considers all of the needed cases:

const compressIPV6 = (ip) => {
  //First remove the leading 0s of the octets. If it's '0000', replace with '0'
  let output = ip.split(':').map(terms => terms.replace(/\b0+/g, '') || '0').join(":");

  //Then search for all occurrences of continuous '0' octets
  let zeros = [...output.matchAll(/\b:?(?:0+:?){2,}/g)];

  //If there are occurences, see which is the longest one and replace it with '::'
  if (zeros.length > 0) {
    let max = '';
    zeros.forEach(item => {
      if (item[0].replaceAll(':', '').length > max.replaceAll(':', '').length) {
        max = item[0];
      }
    })
    output = output.replace(max, '::');
  }
  return output;
}

document.write(compressIPV6('38c1:3db8:0000:0000:0000:0000:0043:000a') + '<br/>');
document.write(compressIPV6('0000:0000:0000:0000:38c1:3db8:0043:000a') + '<br/>');
document.write(compressIPV6('38c1:3db8:0000:0043:000a:0000:0000:0000') + '<br/>');
document.write(compressIPV6('38c1:0000:0000:3db8:0000:0000:0000:12ab') + '<br/>');

If there's more than one occurrence of consecutive '0' octets of the same length, it will only replace the first one. This will work regardless if the repeating zeroes are at the beginning, at the middle or at the end.

Tostti
  • 21
  • 2
  • Finally, an answer that works, as long as the input is fully expanded. It does not handle some valid IPs if they have already been compressed, so you must expand them first. For example, '2001::1:0:0:1428:57ab' becomes '2001:0:1::1428:57ab' and '2001:0:0:1::1428:57ab' becomes '2001::1:0:1428:57ab' when run through this function. These aren't even the same addresses, so be careful! It should be '2001::1:0:0:1428:57ab' by RFC5952 recommendations. – themaninthewoods Mar 22 '23 at 16:03
1

You can use this method in order to compress IPv6 AND remove leading 0s:

   

function compressIPV6(input) {
 var formatted = input.replace(/\b(?:0+:){2,}/, ':');
 var finalAddress = formatted.split(':')
  .map(function(octet) {
   return  octet.replace(/\b0+/g, '');
  }).join(':');
 return finalAddress;
}
document.write(compressIPV6('2001:0db8:0000:0000:0000:0000:1428:57ab') );
Gie
  • 222
  • 3
  • 5
  • Welcom to SO. Please be so kind and write small introductory paragraph, putting your code into context (of the question). – B--rian Jul 25 '19 at 15:17
  • This is not correct. If you change 2 characters in the example address to '2001:0db0:0000:1:0000:0000:1428:57ab' this code produces '2001:db0::1::1428:57ab' which is wrong because it replaced a single '0000' with '::' and it has two '::'. Also, try '2001:0000:0000:1:0000:0000:1428:57ab' and it returns '2001::1:::1428:57ab'. Not only does it have two '::' in it (not allowed), but the second one is actually ':::'. – themaninthewoods Mar 21 '23 at 23:25