Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Text file matches + output 1

Status
Not open for further replies.

PERLNub

Programmer
Jan 28, 2008
3
US
Hi
I've been using PERL for minor forms and such on my web server for a while.. I'm still very much a begginner with the language and now I have a problem.

I have two separate txt files that I need to do a search on. The files are MAC tables from a router and a switch. The "MASTER" file contains all of the MAC addresses + IP addresses from the core router. The "SWITCH" file contains the MAC address and what port on the switch that MAC address is forwarded to. The files are formatted like this:

Code:
MASTER:
4/3 in Location_A xx:xx:xx:xx:xx:xx 10.1.1.1 dynamic
9/1 in Location_B yy:yy:yy:yy:yy:yy 10.2.2.2 dynamic

Code:
SWITCH:
learned xx:xx:xx:xx:xx:xx 1/39	
learned yy:yy:yy:yy:yy:yy 1/13

I need to match MAC address xx:xx:xx:xx:xx:xx from the SWITCH file to the MASTER file and then output all of this info to a third file. The output's format should look something like:
Code:
OUTPUT: 
xx:xx:xx:xx:xx:xx 10.1.1.1 1/39

So this is the program I tried writing:
Code:
#!/usr/bin/perl

# Open the switch text for reading
open SWITCH, "switch.txt" or die "Could not open switch.txt!";

# Open the master text for searching
open MASTER, "master.txt" or die "Could not open master.txt!";

# Open an output file
open OUTPUT, ">output.txt" or die "Could not open output.txt!";

# Loop through the switch text
while(<SWITCH>) {

# Read a line and then cut off the end of line character
   $TheRec = $_; chomp($TheRec);

# The three variables in the exported switch files are delimited by tabs
# Cut them up to get the needed address variable
   ($status, $smac, $port) = split(/\t/, $TheRec, 3);

# While still in that loop check the master.txt file for a match 
   while(<MASTER>) {

# Read another line and cut off the end of line character
      $TheRec2 = $_; chomp($TheRec2);

# Once again the variables needed are tab delimited
# Cut them up into appropriate variables
      ($interface, $mmac, $mip, $type) = split(/\t/, $TheRec2, 4);

# End the MASTER search loop
   }

# Get rid of any spaces in the variables
   ($status, $smac, $port, $interface, $mmac, $mip, $type) =~ s/^\s+|\s+$//g;

# Compare the switch mac with the master mac
# If they match then export all of the relevant data 
# to the output file delimited by tabs
   if($smac == $mmac) {
      print OUTPUT "$smac\t$mip\t$port\n";
   }

# End the SWITCH search loop
}

# Close all of the used files
close SWITCH;
close MASTER;
close OUTPUT;

The problem is that my output comes out very wrong. The MAC address matches up with the port (but I can just get that from the SWITCH text file) but the IP address shows up as the last IP in the MASTER text file.

The MASTER file is roughly 330kb and the SWITCH file is 5kb. I know my mistake lies somewhere in one of the loops since it outputs the very last IP in the MASTER file for every MAC match it makes in the SWITCH file but I can't seem to fix it.

ANY help would be greatly appreciated.
 
Are you sure they are really tab separated?

$interface, $mmac, $mip, $type) = split(/\t/, $TheRec2, 4);

maybe try using \s+ instead?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those who say it cannot be done are usually interrupted by someone else doing it; Give the wrong symptoms, get the wrong solutions;
 
Also.. you need to do your comparison before you end the master loop. You should also use strict!! :)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those who say it cannot be done are usually interrupted by someone else doing it; Give the wrong symptoms, get the wrong solutions;
 
Hi Travs

Yes they are definately tab separated... when I posted the examples here I simply used a space to make it easy to read.

I have not tried using strict yet but I have noticed that the master loop shouldn't end before doing the comparison (which is why it always showed the last IP in the MASTER file). My output wind up being very wrong again when I moved the comparison / end of MASTER loop.

The PC with these files is at the office and I'm now at home... I'll post my output tomorrow.

Thanks!
 
Hey Kevin.. if you read this.. post the link to the site with the color coding again :)

Code:
#!/usr/bin/perl
use strict;

# Open the switch text for reading
open(SWITCH, "<switch.txt") or die "Could not open switch.txt:$!";
my @switch = <SWITCH>;
close SWITCH;
chomp @switch;
# Open the master text for searching
open(MASTER, "<master.txt") or die "Could not open master.txt:$!";
my @master = <MASTER>;
close MASTER;
chomp @master;


# Open an output file
open(OUTPUT, ">output.txt") or die "Could not open output.txt:$!";

# Loop through the switch text
for my $TheRec (@switch) {

# The three variables in the exported switch files are delimited by tabs
# Cut them up to get the needed address variable
   (my $status, my $smac, my $port) = split(/\s+/, $TheRec, 3);
    print "S: $smac\n";
# While still in that loop check the master.txt file for a match
   for my $TheRec2 (@master) {


    # Once again the variables needed are tab delimited
    # Cut them up into appropriate variables
      (my $interface, my $unknown, my $unknown2, my $mmac, my $mip, my $type) = split(/\s+/, $TheRec2, 6);
      print "M: $mmac\n";
      
        # Get rid of any spaces in the variables
        ($status, $smac, $port, $interface, $mmac, $mip, $type) =~ s/^\s+|\s+$//g;

        # Compare the switch mac with the master mac
        # If they match then export all of the relevant data
        # to the output file delimited by tabs
        if($smac eq $mmac) {
            print OUTPUT "$smac\t$mip\t$port\n";
        }

# End the MASTER search loop
   }



# End the SWITCH search loop
}

# Close all of the used files
close OUTPUT;



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those who say it cannot be done are usually interrupted by someone else doing it; Give the wrong symptoms, get the wrong solutions;
 
assuming xx is always digits and there are always two digits, untested code:

Code:
[url=http://perldoc.perl.org/functions/use.html][black][b]use[/b][/black][/url] [green]strict[/green][red];[/red]
[black][b]use[/b][/black] [green]warnings[/green][red];[/red]
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]%switch[/blue] = [red]([/red][red])[/red][red];[/red]
[url=http://perldoc.perl.org/functions/open.html][black][b]open[/b][/black][/url] SWITCH, [red]'[/red][purple]switch.txt[/purple][red]'[/red] or [url=http://perldoc.perl.org/functions/die.html][black][b]die[/b][/black][/url] [red]"[/red][purple]Could not open switch.txt![/purple][red]"[/red][red];[/red]
[olive][b]while[/b][/olive] [red]([/red]<SWITCH>[red])[/red] [red]{[/red]
    [olive][b]if[/b][/olive] [red]([/red][red]/[/red][purple] ([purple][b]\d[/b][/purple][purple][b]\d[/b][/purple]:[purple][b]\d[/b][/purple][purple][b]\d[/b][/purple]:[purple][b]\d[/b][/purple][purple][b]\d[/b][/purple]:[purple][b]\d[/b][/purple][purple][b]\d[/b][/purple]:[purple][b]\d[/b][/purple][purple][b]\d[/b][/purple]:[purple][b]\d[/b][/purple][purple][b]\d[/b][/purple])[purple][b]\s[/b][/purple]+([purple][b]\S[/b][/purple]+)[/purple][red]/[/red][red])[/red] [red]{[/red]
        [blue]$switch[/blue][red]{[/red][blue]$1[/blue][red]}[/red] = [blue]$2[/blue][red];[/red]
    [red]}[/red]
[red]}[/red]
close SWITCH[red];[/red]

[black][b]open[/b][/black] OUTPUT, [red]"[/red][purple]>[/purple][red]"[/red], [red]'[/red][purple]output.txt[/purple][red]'[/red] or [black][b]die[/b][/black] [red]"[/red][purple]Could not open output.txt![/purple][red]"[/red][red];[/red]

[black][b]open[/b][/black] MASTER, [red]'[/red][purple]master.txt[/purple][red]'[/red] or [black][b]die[/b][/black] [red]"[/red][purple]Could not open master.txt![/purple][red]"[/red][red];[/red]
[olive][b]while[/b][/olive] [red]([/red]<MASTER>[red])[/red] [red]{[/red]
    [olive][b]if[/b][/olive] [red]([/red][red]/[/red][purple] ([purple][b]\d[/b][/purple][purple][b]\d[/b][/purple]:[purple][b]\d[/b][/purple][purple][b]\d[/b][/purple]:[purple][b]\d[/b][/purple][purple][b]\d[/b][/purple]:[purple][b]\d[/b][/purple][purple][b]\d[/b][/purple]:[purple][b]\d[/b][/purple][purple][b]\d[/b][/purple]:[purple][b]\d[/b][/purple][purple][b]\d[/b][/purple])[purple][b]\s[/b][/purple]+([purple][b]\S[/b][/purple]+)[/purple][red]/[/red][red])[/red] [red]{[/red]
        [url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] OUTPUT [red]"[/red][purple][blue]$1[/blue] [blue]$switch[/blue]{[blue]$1[/blue]} [blue]$2[/blue][purple][b]\n[/b][/purple][/purple][red]"[/red] [olive][b]if[/b][/olive] [red]([/red][url=http://perldoc.perl.org/functions/exists.html][black][b]exists[/b][/black][/url] [blue]$switch[/blue][red]{[/red][blue]$1[/blue][red]}[/red][red])[/red][red];[/red]
    [red]}[/red]
[red]}[/red]

close MASTER[red];[/red]
close OUTPUT[red];[/red]
[tt]------------------------------------------------------------
Pragmas (perl 5.10.0) used :
[ul]
[li]strict - Perl pragma to restrict unsafe constructs[/li]
[li]warnings - Perl pragma to control optional warnings[/li]
[/ul]
[/tt]

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Well that's really annoying. I go and write a hash-based solution, and Kevin's already posted one. Oh well. I may as wel post it, cos my regexes are slightly different. [sad]
Code:
use strict;
use warnings;

my %macs;

open (MASTER, "master.txt") or die $!;

while (<MASTER>) {
   $macs{lc($1)} = $2 if (/((?:[0-9A-F]{2}:){5}[0-9A-F]{2}).+((?:\d+\.){3}\d+)/i);
}

close(MASTER);

open (SWITCH, "switch.txt") or die $!;

while (<SWITCH>) {
   if (/((?:[0-9A-F]{2}:){5}[0-9A-F]{2}).+(\d+\/\d+)/i) {
      print join("\t", (lc($1), $macs{lc($1)}, $2)), "\n" if (exists($macs{lc($1)}));
   }
}

close(SWITCH);

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
hehehe... I wrote mine several hours ago. Did you forget to refresh the thread before posting?

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Wow guys! Thanks a lot! I'm going to get started and I'll let you guys know which one works out best for me.

Looking at the last two I think I need to brush up on my RE!

Thanks again!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top