notta Posted April 18, 2011 Share Posted April 18, 2011 (edited) Hey guys, I have to create a comma separated string of IP addresses. The string could easily just consist of each IP address, but I want to create ranges to cut down the size of the string. What I mean by that is: 192.168.1.1,192.168.1.2,192.168.1.3,192.168.1.4,192.168.1.5,192.168.1.6 Want to return 192.168.1.1-192.168.1.6 It was more difficult then I thought it would be, but to be honest I'm curious if this could be done more efficiently? I don't like the fact that I'm treating the IP's as strings. I hate the fact that I had to add the leading 0's to sort the array. If I didn't add the leading 0's the array wouldn't be sorted correctly. I put together this small example so you guys could see. I will be dealing with 2000+ IP addresses when I actually go to use this. Any feedback would be appreciated. expandcollapse popup#include Global $aIP = StringSplit("192.168.121.12,192.168.120.176,192.168.134.23,192.168.134.32,192.168.134.67" & _ ",192.168.120.177,192.168.121.18,192.168.134.87,172.16.21.35,192.168.121.13,192.168.120.178" & _ ",192.168.121.1,192.168.121.2,192.168.120.179,192.168.121.10,172.16.33.2,192.168.121.11,192.168.120.180", ",") ;sequences 192.168.120.176,192.168.120.177,192.168.120.178,192.168.120.179,192.168.120.180 ;sequences 192.168.121.1,192.168.121.2 ;sequences 192.168.121.10,192.168.121.11,192.168.121.12,192.168.121.13 Global $newArray[UBound($aIP)][2] $newArray[0][0] = UBound($aIP) - 1 Global $aSequence[1] $aSequence[0] = 0 ;add the leading 0's for sorting purposes #Region add leading 0's for $i = 1 To UBound($aIP) - 1 $split = StringSplit($aIP[$i], ".") $newIP = "" For $j = 1 To UBound($split) - 1 Select Case $split[$j] > 0 AND $split[$j] <= 9 $val = "00" & $split[$j] $newIP &= $val & "." Case $split[$j] >= 10 AND $split[$j] <=99 $val = "0" & $split[$j] $newIP &= $val & "." Case $split[$j] >= 100 AND $split[$j] <=255 $val = $split[$j] $newIP &= $val & "." Case Else MsgBox(16,"","Should never get here") Exit EndSelect Next $newIP = StringTrimRight($newIP, 1) $newArray[$i][0] = $aIP[$i] $newArray[$i][1] = $newIP Next #EndRegion add leading 0's _ArraySort($aIP, 0, 1, 0, 2) _ArraySort($newArray, 0, 0, 0, 1) _ArrayDisplay($aIP, "source array sorted") _ArrayDisplay($newArray, "working array, sorted, with leading 0's") ;delete original array $aIP = "" ;hold the final string of IP's $stringOfIP = "" ;array loop counter $i = 1 ;holds the count of how many IP's currently exist in a sequence $counter = 1 ;holds the element of the first element in a sequence to be compared against $compareVal = 0 If $newArray[0][0] > 1 Then Do If $counter > 1 Then ;if we are in a sequence run If StringLeft($newArray[$i + 1][1], 12) = StringLeft($newArray[$i][1], 12) Then ;check if first 3 octets are equal If (StringRight($newArray[$i + 1][1], 3) - $counter) = StringRight($newArray[$compareVal][1], 3) Then ;compare current IP against first IP in the sequence ReDim $aSequence[UBound($aSequence) + 1] $aSequence[0] += 1 $aSequence[UBound($aSequence) - 1] = $newArray[$i + 1][0] ;add the IP without the leading 0's $counter += 1 $i += 1 _ArrayDisplay($aSequence, "In Sequence") ContinueLoop EndIf EndIf ;write out IP's to the string. No sense creating a range for 2 IP's. Only create an IP range for sequence of IP's > 2 Select Case $counter = 2 for $j = 1 To $aSequence[0] $stringOfIP &= $aSequence[$j] & "," Next Case $counter > 2 $stringOfIP &= $aSequence[1] & "-" & $aSequence[UBound($aSequence) -1] & "," EndSelect ;sequence over. reset variables $compareVal = 0 $counter = 1 ReDim $aSequence[1] $aSequence[0] = 0 $i += 1 Else ;not in a sequence. fresh start; this checks and creates the starting sequence array. Will only be here the first time during the sequence If StringLeft($newArray[$i][1], 12) = StringLeft($newArray[$i + 1][1], 12) Then ;check if first 3 octets are equal If (StringRight($newArray[$i + 1][1], 3) - $counter) = StringRight($newArray[$i][1], 3) Then $compareVal = $i $counter += 1 for $j = 0 To $counter - 1 ReDim $aSequence[UBound($aSequence) + 1] $aSequence[0] += 1 $aSequence[UBound($aSequence) - 1] = $newArray[$i + $j][0] _ArrayDisplay($aSequence, "first 2 elements of sequence") Next $i += 1 ContinueLoop EndIf EndIf ;will only get here when the current 2 array elements are not a sequence $stringOfIP &= $newArray[$i][0] & "," ;reset variables $counter = 1 $i += 1 $compareVal = 0 EndIf Until ($newArray[0][0] - 1) < $i Else MsgBox(0,"","No IP's found") Exit EndIf If StringRight($stringOfIP, 1) = "," Then $stringOfIP = StringTrimRight($stringOfIP, 1) EndIf MsgBox(0,"Final Result",$stringOfIP) Edited April 18, 2011 by notta Link to comment Share on other sites More sharing options...
Malkey Posted April 18, 2011 Share Posted April 18, 2011 I had a little play with your script, and came up with this.Hope it helps.expandcollapse popup#include <Array.au3> Local $stringOfIP Global $aIP = StringSplit("192.168.121.12,192.168.120.176,192.168.134.23,192.168.134.32,192.168.134.67" & _ ",192.168.120.177,192.168.121.18,192.168.134.87,172.16.21.35,192.168.121.13,192.168.120.178" & _ ",192.168.121.1,192.168.121.2,192.168.120.179,192.168.121.10,172.16.33.2,192.168.121.11,192.168.120.180", ",", 2) ;sequences 192.168.120.176,192.168.120.177,192.168.120.178,192.168.120.179,192.168.120.180 ;sequences 192.168.121.1,192.168.121.2 ;sequences 192.168.121.10,192.168.121.11,192.168.121.12,192.168.121.13 #region add leading 0's For $i = 0 To UBound($aIP) - 1 $aIP[$i] = Execute(StringRegExpReplace($aIP[$i], "(\d+)\.(\d+)\.(\d+)\.(\d+)", _ 'StringRight("00" & "\1",3) & StringRight("00" & "\2",3) & StringRight("00" & "\3",3) & StringRight("00" & "\4",3)')) Next #endregion add leading 0's _ArrayDisplay($aIP, "Unsorted") _ArraySort($aIP, 0, 0, 0, 0) _ArrayDisplay($aIP, "Sorted") For $i = 0 To UBound($aIP) - 1 If $i < UBound($aIP) - 2 And $aIP[$i] + 2 = $aIP[$i + 2] Then $stringOfIP &= Execute(StringRegExpReplace($aIP[$i], "(.{3})(.{3})(.{3})(.{3})", _ 'number(\1) & "." & number(\2) & "." & number(\3) & "." & number(\4)')) & "-" $i += 2 Do If $i < UBound($aIP) - 1 Then $i += 1 ;ConsoleWrite($aIP[$i] - 1 & " " & $aIP[$i - 1] & $i & @CRLF) Until $i >= UBound($aIP) - 1 Or $aIP[$i] - 1 <> $aIP[$i - 1] If $i <> UBound($aIP) - 1 Then $i -= 1 EndIf ; Remove the added zeros $stringOfIP &= Execute(StringRegExpReplace($aIP[$i], "(.{3})(.{3})(.{3})(.{3})", _ 'number(\1) & "." & number(\2) & "." & number(\3) & "." & number(\4)')) & "," Next ;ConsoleWrite(StringTrimRight($stringOfIP, 1) & @CRLF) MsgBox(0, "Final Result", StringTrimRight($stringOfIP, 1)) Link to comment Share on other sites More sharing options...
notta Posted April 18, 2011 Author Share Posted April 18, 2011 Wow, Malkey that really streamlined it. I really appreciate you taking the time to do that.I was swamped all day at work today so I couldn't post. Regular expressions are killer for me, but I'm going to sit down now and go through how you did this. Thanks again. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now