Sort IP Addresses Using Perl
When dealing with lists of IP addresses, it was common for the numbers to merge together and lose track of duplicates, bad IP addresses etc. This Perl script helps you extract valid IPs from a block of text.
Sort IP Addresses Using Perl
This program gives you a Tk Box to paste some IPv4 looking text. After you have a block of text with IP addresses in it, you click “sort” and here is what happens:
- Duplicates IP Are Removed (Deduplication)
- Invalid IP/Text is skipped
- IP Addresses are sorted
- Valid IP printed out
- Count/statistics of lines, ip addresses, etc
What to Learn from this Perl Code:
We try to follow the Perl style guide by Damon Conway, but we have our preferences too. This is more of a lesson in how to solve simple problems. This would not be a great way to sort through records that have millions of entries – for that you’d want to optimize certain aspects and verify you are not soaking up too much memory. For the purpose of a few hundred IP addresses though, this script works great.
- Tk (message boxes, entry boxes, buttons, basic form setup)
- IPv4 Extraction
- Operating System Detection
- Win32 Console Management
- Sorting and Working with Perl Hashes
Typical Use
When working for a client, we processed many firewall requests (sometimes up to 50 changes per day). They often provided us with spreadsheets that were manually typed up and contained duplicates, errors, and sometimes missing ip addresses. It was maddening to try and review a list and not make mistakes. Perl is great for automation tasks like this, even if Tk is an outdated interface – it works!
Known Issues
Valid IP addresses come in many forms. Perhaps you don’t want anything except the x.x.x.x format? We are only looking at the x.x.x.x format! So if you need a different type of input, you will have to rewrite your error checking!
Source Code for Sorting IP Addresses:
(Don’t forget that this removes duplicates and matches valid IP only too!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
#!/usr/bin/perl # Sorter helps to process firewall requests, especially for a large change # or especially where the request has a random order to the IP addresses # it's often very difficult to mentally sort the list and remove duplicates # this program assists by doing the sort/unique for you for a side by side stare # and compare in whatever program you are building a firewall. # note that this is not a valid IP checker! # IPs can be in the form of a, a.b, a.b.c, or a.b.c.d # IPs are 32 bit binary numbers! # this is just for sorting strings that look like IPs # there is NO error checking # KNOWN ISSUE: # 1.1.1.1-1.1.1.10 only gets 2 ip addresses # 1.1.1.1/16 shows as ip 1.1.1.1, not the actual network # INPUT: block of text that contains ipv4 addresses in x.x.x.x format # OUTPUT: sorts ipv4 for a side by side comparison (like comparing spreadsheet cells use warnings; use strict; use Tk; use Regexp::Common qw /net/; use constant VERSION => ' v2.2'; # hide the console, if windows BEGIN { if ($^O eq 'MSWin32') { require Win32::Console; Win32::Console::Free( ); } } my $instructions1 = qq~1. Paste Text Containing IPs~; my $instructions2 = qq~2. Sort Output ~; my $h = 45; # rows my $w = 22; # cols my $g = MainWindow->new; # title bar of main window $g->title('IP Sorter ' . VERSION); # pixels window size (resizable later via mouse, w x h) $g->geometry("320x659"); # setup some frames in the main window # the main frame my $mF = $g->Frame( -background => "red")->pack( -side => 'top', -fill => 'x'); # Frame 1 my $f1 = $mF->Frame( -background => "grey")->pack( -side => 'left', -fill => 'y'); # Frame 2 my $f2 = $mF->Frame( -background => "grey")->pack( -side => 'right', -fill => 'y'); # fill f1 Frame my $inLabel = $f1->Label( -text => $instructions1)->pack( -side => "top"); my $input = $f1->Text( -background => 'white', -foreground => 'black', -height => $h, -width => $w)->pack( -side => "bottom"); # fill f2 Frame and Command Button + Options my $outCommand = $f2->Button( -text => $instructions2, -command =>\&process)->pack( -side=>"top"); my $output = $f2->Text( -background => 'white', -foreground => 'black', -height => $h, -width => $w)->pack( -side => "bottom"); # stop building TK widgets, the rest is subroutines MainLoop; sub process { my %data; my $found = 0; my $unique = 0; my $lines = 0; # delete the output to prepare for use $output->delete('0.0', 'end'); # get text block from input my $text = $input->get('1.0','end'); # process the text field into an array of lines my @data = split /\n/,$text; # count how many elements are in raw data $lines = @data; while (<@data>) { # TODO: add the case for x.x.x.x-x.x.x.y to at least warn. if (m/($RE{net}{IPv4})/) { my $ip = $1; # so I'm replacing the / with a - $ip =~ s#\/#-#; # load the index of the hash $data{$ip} = 1; # count it as a found IP $found++; } } # keys are always unique in a hash, # print them out in the text box foreach my $u (sort keys %data) { $output->insert('end',"$u\n"); # count how many were unique $unique++; } # status of what was found $g->messageBox( -message => "LINES: $lines\nFOUND: $found\nUNIQUE: $unique", -type => "OK"); } # sample data for cut and paste while testing __DATA__ 1.19.247.12-1.19.247.14 range 1.19.247.17 1.1.1.1 2.2.2.2 (2) 1.15.8.134 post pre 1.15.8.139 1.2.199.96 1.2.199.96 duplicate 1.2.212.84 empty 555.55.5.5 (wrong) |