Re: Compare values of two or more arrays
[email protected] (Rob Dixon)
| Newsgroups | perl.beginners |
|---|---|
| Message-ID | <[email protected]> |
Mimi Cafe wrote:
> I am trying to compare one or more lists against a master record file and
> find out elements of the master record which are not in the other records
> and compile new lists of elements which are in the master data, but not
> found in the other records.
>
> This works to fine, but the output list is random to some extend. The script
> is run with command line arguments specifying the master data file and the
> other file(s) to compare:
>
> script --master masterrecord.txt --compare compare_file1 --compare
> compare_file2
I'm not sure what your question is, or what you mean by 'the output list is
random'. But I can comment on your code.
> ##########################################
>
> #!c:\perl\bin\perl.exe -w
The #! line is only noticed by Unix-type shells and is ignored completely on a
Windows platform, so it's best just to leave it off. (Perl itself still takes
note of the command line switches specified here and so still actions your -w,
but see below.).
> use strict;
> #use warnings;
It's always better to
use warnings;
rather than using the -w command-line switch.
> #use diagnostics;
> use Getopt::Long;
>
> # Perl script to compare WSUS and AV clients against AD computers and create
> a report of AD
> # computers not found in the WSUS or AV list.
>
> use constant DEFAULT_REPORTDIR => 'CompareReport';
> #use constant DEFAULT_WORKINGDR => '.';
> my ($master, @compare, $help);
>
>
> Getopt::Long::Configure ("permute","ignorecase");
>
> GetOptions(
> "master=s" => \$master,
> "compare:s" => \@compare,
> "help|?!" => \$help,
> );
>
> usage() if $help;
>
> foreach (@compare){
> die "File $_ does not exist or it's empty. Please check the file try
> again.\n" unless -s $_;
> }
If your die string ends with a newline then the output won't include the source
file and line number, which may be useful when you are debugging. Like this
die "failed";
produces
failed at E:\Perl\source\x.pl line 14.
while
die "failed\n";
produces just
failed
> my $outputdir = DEFAULT_REPORTDIR;
> unless (-d $outputdir){
> mkdir ($outputdir) or die "could not create dir for $outputdir: $!\n";
> }
mkdir will only succeed if the parent directory exists. That is to say,
mkdir 'path/to/my/directory';
will fail unless path/to/my exists.
It may be useful to take a look at the mkpath function in File::Path, which will
also create any intermediate directories in the path.
> # Read the master list and populate our array.
> open (MASTERFILE, "<", $master) or die "Could not open $master for reading:
> $!\n";
> my @master_clients = <MASTERFILE>;
> chomp(@master_clients);
> close MASTERFILE;
It is better to use lexical file handles, as in
open my $masterfh, '<', $master or die "Could not open $master for reading: $!";
If I was writing this I would say
my @master_clients = do {
open my $fh, '<', $master or die "Could not open $master for reading: $!";
<$fh>;
};
chomp @master_clients;
> my (%inputclient,$list);
It is always best to declare variables as close as possible to the point of use.
Declaring %inputclient here means that the contents the files in @compare will
be accumulated to the hash, and when you are processing the last file in the
list your output will show only those values that are in /none/ of the files in
the list. Is this what you mean by the output list being random?
I'm fairly certain that you want a per-file report, ans so the hash should be
declared within this for loop.
> # Read the other files and compare the content to the master client list.
> foreach $list (@compare){
foreach my $list (@compare) {
> # Output file name set of element curerently processed.
> # Open file to read from.
>
> open(INFH, "$list") or warn "Could not open $list for reading: $!\n";
This will give you a warning but still continue to use an invalid file handle.
> while (<INFH>){
> chomp;
> $inputclient{"$_"} = $_;
> }
> close INFH;
{
open my $fh, '<', $list or do {
warn "Could not open $list for reading: $!";
next;
};
while (<$fh>) {
chomp;
$inputclient{$_}++;
}
}
> my $outputfile = $list;
> my (@missing_clients, %outputclient);
>
> foreach my $aditem (@master_clients){
> push (@missing_clients, $aditem) unless exists $inputclient{"$aditem"};
> }
>
>
> open (OUTPUTFILE, ">$outputdir\\$outputfile") || die "Could not open
> $outputfile: $!\n";
> foreach (@missing_clients){ print OUTPUTFILE "$_\n";}
> close (OUTPUTFILE);
{
open my $fh, '>', "$outputdir\\$list";
print $fh "$_\n" foreach @missing_clients;
}
> }
>
>
> # Subroutine to print example of script usage.
>
> sub usage {
> print "\nUSAGE:\t$0 --master master_file --comapre file1 --comapre
> file2\n\n";
> print "\tExample: $0 --master adlist --compare avlist --comapre file2\n";
> print "\t$0 --help or --? should displays this usage summary.\n";
> exit;
>
> }
HTH,
Rob