最近在处理IPV6的校验,有一个需求:要求能校验出同一个IPV6地址的简写地址和完整地址,这就需要我们把简写的IPv6地址还原,同时还能把ipv6地址简化。
下面分享给一个我使用的JS方法:
| // 简写ipv6
ipv6AbbreFunc () {
// 简写ipv6,只针对0操作:
// 1.4位16进制数的段中高位0可以省略,
// 2.相邻全0段,简写成::,双冒号只有一次
let value = '1000:0000:0001:0000:0001::0000'
// 补全ipv6地址
let fullIPv6 = this.ipv6FillFunc(value)// abcd:0000:0000:0000:0001:0000:0000::0001
console.log(fullIPv6)
// 4位16进制数的段中高位0可以省略,
let v6Arr = fullIPv6.split(':')
v6Arr.forEach((item, index) => {
v6Arr[index] = v6Arr[index].replace(/^0{1,3}/, '')
})// v6Arr ['abcd','0','0','0','1','0','0','1']
console.log(v6Arr)
// 查找要简写的全0段的位置
let v6Arr2 = v6Arr
v6Arr2.forEach((item, index) => {
if (v6Arr2[index] != '0') {
v6Arr2[index] = '-'
}
})// v6Arr2 ['-','0','0','0','-','0','0','-']
console.log(v6Arr2)
// 找出最长重复字符的字符
let v6Str = v6Arr2.toString()// '-,0,0,0,-,0,0,-'
v6Str = v6Str.replace(/,/g, '')// '-000-00-'
console.log(v6Str)
var strmore = this.maxRepeactStr(v6Str)
console.log(strmore)
let maxRepeactString = ''
if (strmore.length === 0) {
return value
} else if (strmore.length >= 1) { // 有重复的0
maxRepeactString = strmore[0]
console.log('maxRepeactString:' + maxRepeactString)
let location = v6Str.indexOf(maxRepeactString)
console.log('location:' + location)
// 替换整理
let arr = []
v6Arr = fullIPv6.split(':')
v6Arr.forEach((item, index) => {
arr[location] = '::'
if (index >= location && index < location + maxRepeactString.length) {
arr[index] = ''
} else {
arr[index] = item
}
})
console.log(arr)
let abbre = ''
arr.forEach((item, index) => {
if (item === '::' || item === '' || index === 0 || index === parseInt(location)) {
abbre = abbre + '' + item
} else {
abbre = abbre + ':' + item
}
})
abbre = abbre.replace(/::+/g, '::')
console.log(abbre)
return abbre
}
},
// 补全ipv6
ipv6FillFunc (value) {
let perlipv6regex = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|:)))(%.+)?\s*$/
if (value !== '' && !perlipv6regex.test(value)) {
return false
}
let v6Arr = value.split(':')
if (v6Arr[0] === '') {
v6Arr.shift()
} else if (v6Arr[v6Arr.length - 1] === '') {
v6Arr.pop()
}
// 转换点分十进制的v4写法
let map10To16 = {
0: '0',
1: '1',
2: '2',
3: '3',
4: '4',
5: '5',
6: '6',
7: '7',
8: '8',
9: '9',
10: 'a',
11: 'b',
12: 'c',
13: 'd',
14: 'e',
15: 'f'
}
if (v6Arr.length > 1 && v6Arr[v6Arr.length - 1].indexOf('.') !== -1) {
let ten = v6Arr.pop()
let tenArr = ten.split('.')
tenArr.forEach(tenItem => {
v6Arr.push('00' + map10To16[Math.floor(tenItem / 16)] + map10To16[tenItem % 16])
})
}
let fillStr = ''
if (v6Arr.length !== 8) {
let length = 9 - v6Arr.length
for (let i = 0; i < length; i++) {
fillStr += '0000:'
}
}
let num16 = ''
v6Arr.forEach((e) => {
e = e.toLocaleLowerCase()
if (e !== '') {
num16 += (e.length === 4 ? e : '0'.repeat(4 - e.length) + e) + ':'
} else {
num16 += fillStr
}
})
return num16.substr(0, 39)
},
// 找到最长的重复子串
maxRepeactStr (str) {
let reg = /(\w)\1+/g
let a = []
let max = ['']
while ((a = reg.exec(str)) != null) {
if (max[0].length < a[0].length) {
max[0] = a[0]
} else if (max[0].length == a[0].length) {
max.push(a[0])
}
}
return max
} |
网友评论