Solved

Perl regex help

Posted on 2011-02-27
7
261 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
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 

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

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Suggested Solutions

Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
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…
This video discusses moving either the default database or any database to a new volume.

747 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

15 Experts available now in Live!

Get 1:1 Help Now