john.tm has asked for the wisdom of the Perl Monks concerning the following question:

i have a master csv file and a daily csv file, i need to compare email server addresses in the daily file against the addresses in master file and print a list of any that are not on the master sheet, the problem is i only need to compare up to the 1st fullstop, ie as long as the first part of the address matches thats ok it does not matter whats after the fullstop. however if there is no match the whole address needs to be displayed on screen.

<p> INPUT john.co.uk,Acton,Backup,Team,backup,bkup-01,External gim.com,Acton,Backup Team,backup,bumas1,internal jeff.be.com,Acton,Backup Team,backup,bumas1,internal scream,Acton,Backup Team,backup,bumas1,internal ACTDFVUA.co.uk,Acton,Backup Team,backup,imrn,internal <c> <p> INPUT1 Server,Type,Reason,Data at Risk,Ticket,Resolution john.com,F,No email received,YES gim,Acton,Backup Team,backup,bumas1,internal elephant.com,F,No email received,YES jeff.co.com,F,No email received,YES scream,S,1 email received,Some banana,F,No email received,YES

result would be print "elephant.com NOT KNOWN PLEASE UPDATE " print "banana NOT KNOWN PLEASE UPDATE " </c>

this is what i use at present

open (INPUT1,"$INFILE1") or die " cannot open $INFILE1"; while (<INPUT1>) { @INFILE = ($_); chomp($_); @FAILS = split (/,/,); @SERVER = splice (@FAILS,0,1); @TYPE = splice (@FAILS,0,1); @REASON = splice (@FAILS,0,1); @STATUS = splice (@FAILS,0,1); @TICKET = splice (@FAILS,0,1); @RESOLUTION = splice (@FAILS,0,1); foreach $server1 (@SERVER) { $servers = $server1; $servers =~ tr/[a-z]/[A-Z]/; } foreach $type1 (@TYPE) { $types = $type1; $types =~ tr/[a-z]/[A-Z]/; } if ( "$types" eq "F") { $types="BACKUP FAILED"; } else { if ("$types" eq "S") { $types="SKIPPED FILES"; @TICKET="DO NOT RAISE TICKET"; }} $value= &read_location; if ("$value" ne "0"){ print "@SERVER NOT KNOWN PLEASE UPDATE \n"; } } sub read_location { open (INPUT,"$INFILE") or die " cannot open $INFILE "; while (<INPUT>) { $result = 1; chomp($_); @array = ($_); @all = split (/,/,); @machine = splice (@all,0,1); @loc = splice (@all,0,1); @team = splice (@all,0,1); @software = splice (@all,0,1); @backup_server = splice (@all,0,1); @owner = splice (@all,0,1); foreach $machine1 (@machine) { $machines = $machine1; $machines =~ tr/[a-z]/[A-Z]/; } if ("$servers" eq "$machines"){ printf OUTPUT ("%s %s %s,%s,%s,%s,%s,%s,%s,%s,%s,%s, \n",$ +todaysday,$thismonth,$year,@loc,@team,@owner,$servers,$types,@REASON, +@STATUS,@TICKET,@RESOLUTION, ); close (INPUT); return 0; } } } close (INPUT); close (OUTPUT);

Replies are listed 'Best First'.
Re: compare csv files only to first fullstop character
by kcott (Archbishop) on May 08, 2014 at 12:43 UTC

    G'day john.tm,

    Welcome to the monastery.

    Use Text::CSV instead of rolling your own solution with all those split and splice statements.

    Populate a hash with the first part of the address from the master file then compare with addresses from the daily file.

    This code shows the basic idea of how to do that:

    #!/usr/bin/env perl -l use strict; use warnings; my %seen; for (qw{john.co.uk gim.com}) { ++$seen{get_first_part_of_address($_)}; } for (qw{john.com gim elephant.com banana}) { print unless $seen{get_first_part_of_address($_)}; } sub get_first_part_of_address { return (split /\./, shift)[0] }

    Output:

    elephant.com banana

    -- Ken

Re: compare csv files only to first fullstop character
by GrandFather (Saint) on May 08, 2014 at 12:24 UTC

    There is altogether too much wrong with that code to comment on everything. So a brief list of the highlights then some sample code that does what you seem to want:

    1. Always use strictures (use strict; use warnings; - see The strictures, according to Seuss).
    2. In many places you use an array (e.g. @SERVER) instead of a scalar ($server).
    3. Use the three parameter open and lexical file handles (open my $fIn, '<', $filename or die "Can't open '$filename': $!\n")
    4. Don't use global variables.
    use strict; use warnings; my $masterStr = <<EOF; john.co.uk,Acton,Backup,Team,backup,bkup-01,External gim.com,Acton,Backup Team,backup,bumas1,internal jeff.be.com,Acton,Backup Team,backup,bumas1,internal scream,Acton,Backup Team,backup,bumas1,internal ACTDFVUA.co.uk,Acton,Backup Team,backup,imrn,internal EOF my $dailyStr = <<EOF; Server,Type,Reason,Data at Risk,Ticket,Resolution john.com,F,No email received,YES gim,Acton,Backup Team,backup,bumas1,internal elephant.com,F No email received,YES jeff.co.com,F No email received,YES scream S,1 email received,Some banana,F,No email received,ES EOF my %masters = loadMasters(); my @dateParts = localtime (); my ($day, $month, $year) = @dateParts[3 .. 5]; $year += 1900; $month += 1; #open my $dailyIn, '<', $INFILE1 or die " cannot open '$INFILE1': $!"; open my $dailyIn, '<', \$dailyStr; <$dailyIn>; # Skip header line while (defined (my $line = <$dailyIn>)) { chomp $line; my ($server, $type, $reason, $status, $ticket, $resolution) = split ',', $line; $_ = uc $_ for $server, $type; $_ //= '-- missing --' for $status, $ticket, $resolution; if ($type eq "F") { $type = "BACKUP FAILED"; } elsif ($type eq "S") { $type = "SKIPPED FILES"; $ticket = "DO NOT RAISE TICKET"; } (my $serverKey = $server) =~ s/\..*//; if (!exists $masters{$serverKey}) { print "'$server' not known please update\n"; next; } printf "%s %s %s,%s,%s,%s,%s,%s,%s,%s,%s,%s, \n", $day, $month, $year, $masters{$serverKey}{loc}, $masters{$serverKey}{team}, $masters{$serverKey}{owner}, $server, $type, $reason, $status, $ticket, $resolution; } sub loadMasters { my %masters; #open my $masterIn, '<', $INFILE1 or die " cannot open '$INFILE1': + $!"; open my $masterIn, '<', \$masterStr; while (defined (my $line = <$masterIn>)) { chomp $line; my ($machine, $loc, $team, $software, $backup, $owner) = split + ',', $line; (my $machineKey = uc $machine) =~ s/\..*//; warn "Multiple servers match '$machineKey'!\n" if exists $masters{$machineKey}; $masters{$machineKey} = { server => $machine, loc => $loc, team => $team, software => $software, backup => $backup, owner => $owner }; } return %masters; }

    Prints:

    9 5 2014,Acton,Backup,bkup-01,JOHN.COM,BACKUP FAILED,No email received +,YES,-- missing --,-- missing --, 9 5 2014,Acton,Backup Team,internal,GIM,ACTON,Backup Team,backup,bumas +1,internal, 'ELEPHANT.COM' not known please update 9 5 2014,Acton,Backup Team,internal,JEFF.CO.COM,F NO EMAIL RECEIVED +,YES,-- missing --,-- missing --,-- missing --, 'SCREAM S' not known please update 'BANANA' not known please update

    The open my $masterIn, '<', \$masterStr; stuff uses a string as a file which is handy for test code like this. The commented out open lines are closer to what you would use for real.

    You should really use Text::CSV to manage csv files instead of hand rolled split code.

    Update: fixed typo in module name.

    Perl is the programming world's equivalent of English
      please see screen print when i run this script
      C:\scripts>new2.pl Backslash found where operator expected at C:\scripts\new2.pl line 47, + near "(my $serverKey = $server) =~ s/\" (Might be a runaway multi-line // string starting on line 38) (Missing operator before \?) Global symbol "$serverKey" requires explicit package name at C:\script +s\new2.pl line 38. syntax error at C:\scripts\new2.pl line 47, near "(my $serverKey = $se +rver) =~ s /\" Global symbol "$serverKey" requires explicit package name at C:\script +s\new2.pl line 49. Global symbol "$serverKey" requires explicit package name at C:\script +s\new2.pl line 57. Global symbol "$serverKey" requires explicit package name at C:\script +s\new2.pl line 58. Global symbol "$serverKey" requires explicit package name at C:\script +s\new2.pl line 58. Execution of C:\scripts\new2.pl aborted due to compilation errors.
        Your Perl is probably older than 5.10, so you can't use the defined-or operator. See perl5100delta for details.
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
        Check line 38. If it is like this $_ ///= '-- missing --' for $status, $ticket, $resolution; then delete one of the /, there should only be 2.
        poj
        i replaced the new defined-or operator on line 38. with ||.
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: compare csv files only to first fullstop character
by ww (Archbishop) on May 07, 2014 at 23:33 UTC

    What have you tried?
    What is your problem?

    If your problem is that you want us to write it for you, then you do have a serious problem. We'll happily help you along in your efforts to learn Perl... but we're not about providing a free code-writing service.


    Questions containing the words "doesn't work" (or their moral equivalent) will usually get a downvote from me unless accompanied by:
    1. code
    2. verbatim error and/or warning messages
    3. a coherent explanation of what "doesn't work actually means.
      i hope this is clearer