Solved

Perl regex help

Posted on 2011-02-27
7
262 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

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 500 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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

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…
There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
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…
Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…

911 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now