Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 365
  • Last Modified:

Perl errors help

Hello,
Wondering if anyone cam help with with the below error.
This program uses a soundex subroutine, you indicate a lastname
and the program calls system funtion finger and displays the info.
They key is you can misplell the name and it will still pull the user info.

I don't get it since the subroutine soundex works when ran seperate.
I added the corresponding numbers to the lines where the errors are indicated.

Error:
Use of uninitialized value in transliteration (tr///) at ./final4 line 123 (#1)
    (W uninitialized) An undefined value was used as if it were already
    defined.  It was interpreted as a "" or a 0, but maybe it was a mistake.
    To suppress this warning assign a defined value to your variables.

    To help you figure out what was undefined, perl will try to tell you the
    name of the variable (if any) that was undefined. In some cases it cannot
    do this, so it also tells you what operation you used the undefined value
    in.  Note, however, that perl optimizes your program and the operation
    displayed in the warning may not necessarily appear literally in your
    program.  For example, "that $foo" is usually optimized into "that "
    . $foo, and the warning will refer to the concatenation (.) operator,
    even though there is no . in your program.

Use of uninitialized value $fc in substitution (s///) at ./final4 line 124 (#1)
Use of uninitialized value $fc in concatenation (.) or string at ./final4 line
        127 (#1)
Use of uninitialized value $f in concatenation (.) or string at ./final4 line
        129 (#1)

#!/usr/bin/perl
use diagnostics;
use strict;
use warnings;
#use Data::Dumper;

my $num = 0;

 if (@ARGV != 1)

 {
     print "\nUsage: $0 LastName\n\n";
     exit(1);
 }
 chomp $ARGV[0];


#-------------------


open (IN,"/etc/passwd");
my @wholeFile = <IN>;
close IN;

foreach my $line (@wholeFile)
{
    my $userid = &get_user_id($line);
    my $lastname = &get_last_name($line);
  #  print "$userid has a last name of $lastname!\n";

 if(&soundex($lastname) eq &soundex($ARGV[0]))

     {
         my @args = ("finger", $userid);
         system (@args);
         $num++;
     }
}

print "\nThe name you were looking for, ".$ARGV[0]." converted to ".soundex($ARGV[0])."\n";



 if ($num == 0)

     {

         print "finger: ".$ARGV[0].": no such user.\n\n";

     }

#---------------userid----------------------

sub get_user_id

 {
my @uname = grep /^\w.*?/, @wholeFile;
#convert array into string
my $string = join('',@uname);

my @data1 = split (/\n/, $string);

      @data1 = split(/:/,shift);
    # print "$userid[0]";
     return $data1[0];
 }

#-----------lastname-------------

sub get_last_name
 {
my @uname = grep /^\w.*?/, @wholeFile;
#convert array into string
my $string = join('',@uname);

my @data1 = split (/\n/, $string);

      @data1 = split (/:/,shift);

     if ($data1[4] ne "" || $data1[4] ne " ")
     {
         $data1[4] =~ s/,.*?//g;
         $data1[4] =~ /(\S+\s\S+\s*\S*)/g;
         return $1;
     }
     else
     {
         print "No last name provided\n";
     }
 }

 
 

#--------------soundex subroutine---------------------------------------------
sub soundex
{

  my $temp = uc shift;    # gets the name passed to the function
                           # and uppercases it

$temp =~ s/^[^A-Z]//;   # remove first character if not letter

# Eliminate doubled-letters

my @x = split(//,$temp);
$temp = '';
my $lastx = '';

foreach my $x ( @x)
{
    if ( ( $lastx eq '' ) || ( $x ne $lastx ) )
    {
        $temp .= $x;
        $lastx = $x;
    }
}
#print STDERR "$temp\n";

# Split into first letter and the rest
my ($f, $fc) = ($temp =~ /(\w)(\w+)/);
 
# soundex weighting
123 $fc =~ tr/AEHIOUWYBFPVCGJKQSXZDTLMNR/00000000111122222222334556/;
124 $fc =~  s/0+//g; #gets rid of extra 0's

# first four digits, pad with zeroes on right if needed
127 $fc = substr($fc.'000',0,4);   
 
129 my $sdxValue = $f.$fc;

  return $sdxValue;   
    
}

Open in new window

0
fac66
Asked:
fac66
1 Solution
 
sjklein42Commented:
Line 78 is wrong:

      @data1 = split (/:/,shift);

Open in new window

See line 76 also.  These two lines must have a typo or something.  That is the trigger of the error.
0
 
APNFSSCCommented:
I think you should test to see if a last name is returned by get_last_name, if it's blank then you'll get the error i think.

foreach my $line (@wholeFile)
{
    my $userid = &get_user_id($line);
    my $lastname = &get_last_name($line);
  #  print "$userid has a last name of $lastname!\n";
 unless($lastname){
 print "Lastname empty skipping $userid\n";
next;
 }

 if(&soundex($lastname) eq &soundex($ARGV[0]))

     {
         my @args = ("finger", $userid);
         system (@args);
         $num++;
     }
}

0
 
fac66Author Commented:
That is it.
The problem is the data I need is at element 4 of the array which is suppose to hold the full name.
Some fields are blank.
Most names have 1st & last, while some have a middle also.
Some people even have 3 or 4 names.
How do I filter the last name?
Any ideas? I have tried several regex filters and cannot get it.
Any help would be appreciated.
sub get_last_name
 {
my @uname = grep /^\w.*?/, @wholeFile;
#convert array into string
my $string = join('',@uname);
#split at newlines
my @data1 = split (/\n/, $string);
      #split at colons
      @data1 = split (/:/,shift);

     if ($data1[4] ne "" || $data1[4] ne " ")
     {
         $data1[4] =~ s/,.*?//g;
         $data1[4] =~ /(\S+\s\S+\s*\S*)/g;
                 return $1;
     }

}

Open in new window

0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
APNFSSCCommented:
Let's say your data1 array item 4 has the following in it

$date1[4]='John Paul Smith';

Then you could split that out into another array and choose the last element simular to below... not sure if this will work for you as i cannot see that data you have.

my @name_array = split(/ /,$data1[4]);
$lastname = $name_array[-1];
0
 
fac66Author Commented:
I need to keep debuging but I think that worked.. thank you!
0
 
FishMongerCommented:
You have a lot of major problems with that script.

Here are some of the problems.

You have no error handling.

You should ALWAYS check the return code of an open call to make sure it was successful and take action if it wasn't.  You should use a lexical var for the filehandle and the 3 arg form of open.

You're slurring the file into an array and then looping over the array instead of processing the file line-by-line.

For every line in the file file you're passing it to 2 almost identical subroutines each of which do a grep on the entire file each time they're called.

The array that you build from that grep statement is then joined into a single string and then that string is split to create a duplicate of the original array.  Then you throw all that away when you use another split statement to overwrite the array you just created.

There are other issues, but you should address those first.

0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now