?
Solved

Perl regex help

Posted on 2011-02-27
7
Medium Priority
?
269 Views
Last Modified: 2012-05-11
Hello,
What I am attempting is pulling the username and first/last name from the etc/passwd file

username:x:1333:1333:fnamel name,,,:/home/smele:/bin/bash
username:x:1334:1334:fname lname,,,:/home/tjmullins:/bin/bash

The code below is pulling mutiple duplicate entries and throws an error:

Use of uninitialized value $x in concatenation (.) or string at ./part2c line
        27 (#1)

Outside the loop it only prints the last item on the array.

Any help would be appreciated.
open (IN,"/etc/passwd");
my @wholeFile = <IN>;
close IN;

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

my @data = split (/\n/, $string);
 
 #filter out username
foreach my $line(@data) {
my @id = ($line  =~ /\s*(\S+)\:\w\:\d+\:\d+\:(\S+\s+\S+)\S+\S+\S+\:\/\S+\/\S+\:\/\S+\/\S+\s*$/mg);
my $z = $1;
#print "$z\n";
my $x = $2;
print "$x\n";
 
}

Open in new window

0
Comment
Question by:fac66
  • 4
  • 3
7 Comments
 
LVL 35

Expert Comment

by:Terry Woods
ID: 34993180
Try swapping:

print "$x\n";

With:

  if (defined $x) { print "$x\n" };
0
 

Author Comment

by:fac66
ID: 34993361
Thanks for the reponse.

This is in a sub function
The return is only returning the last item in the array.
How do I return all users?
sub get_user_id {
 
my @uname = grep /^\w.*?/, @wholeFile;
#convert array into string
my $string = join('',@uname);
#print $string;

#splits at line breaks
my @data = split (/\n/, $string);
my $z;
foreach my $line(@data) {
 my @id = ($line  =~ /\s*(\S+)\:\w\:\d+\:\d+\:(\S*\s*\S*\s*\S*)\S+\S+\S+\:\/\S+\/\S+\:\/\S+\/\S+\s*$/mg);
 $userid;= $1;
 #if (defined $userid ) { print "$userid\n" };

 }

return $userid;
 }

Open in new window

0
 
LVL 35

Expert Comment

by:Terry Woods
ID: 34993615
To return an array of userids, do something like this:
sub get_user_id {
 
my @uname = grep /^\w.*?/, @wholeFile;
#convert array into string
my $string = join('',@uname);
#print $string;

#splits at line breaks
my @data = split (/\n/, $string);
my $z;
my @userids = ();
foreach my $line(@data) {
 my @id = ($line  =~ /\s*(\S+)\:\w\:\d+\:\d+\:(\S*\s*\S*\s*\S*)\S+\S+\S+\:\/\S+\/\S+\:\/\S+\/\S+\s*$/mg);
 $userid;= $1;
 if (defined $userid ) { 
   push(@userids,$userid);
 }

}
return @userids;

}

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!

 

Author Comment

by:fac66
ID: 34993949
Actually I rewrote it and I think I just about got it.

Although I am getting errors in a subroutine that works when it's ran seperate.
now. I put the numbers next to the lines the errors are in the code.
Anyone got any ideas?

 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
 
LVL 35

Expert Comment

by:Terry Woods
ID: 34994228
If your /etc/passwd is like mine, then you won't have a first and last name on every line. I believe some cases are resulting in an uninitialised value, which is being passed along to the code that produces the error. Try tightening up the handling where the expected values aren't found.
0
 

Author Comment

by:fac66
ID: 34994267
Not sure what you mean, keep in mind I am pretty new to \Perl.
0
 
LVL 35

Accepted Solution

by:
Terry Woods earned 2000 total points
ID: 34994306
For example, I think in cases like:
username:x:1334:1334::/home/tjmullins:/bin/bash

Your get_last_name sub is likely to return an undefined value from $1, because:
/(\S+\s\S+\s*\S*)/g;
doesn't match.
0

Featured Post

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!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I have been pestered over the years to produce and distribute regular data extracts, and often the request have explicitly requested the data be emailed as an Excel attachement; specifically Excel, as it appears: CSV files confuse (no Red or Green h…
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans
Suggested Courses

862 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question