0

I have a perl array where I only want to loop through elements 2-8.

The elements are only meant to contain numbers, so if any of those elements contain a letter, I want to set an error flag = 1, as well as some other variables as seen.

The reason I have 2 error flag variables is due to scope rules within the loop.

fields is an array, I created by splitting another irrelevant array by the " " key.

So, when I try to print error_line2, error_fname2 from outside the loop, I get this:

Use of uninitialized value $error_flag2 in numeric eq (==) 

I don't know why, because I've initialized the value within the loop and created the variable outside the loop. Not sure if I'm even looping to find characters correctly, so then it's not setting the error_flag2 = 1.

Example line:

bob hankerman 2039 3232 23 232 645 64x3 324

since element 7 has the letter 'x' , I want the flag to be set to 1.

#!/usr/bin/perl
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);

my $players_file = $ARGV[0];
my @players_array;

open (my $file, "<", "$players_file")
    or die "Failed to open file: $!\n";
while(<$file>) {
    chomp;
    push @players_array, $_;
}
close $file;
#print join "\n", @players_array;

my $num_of_players = @players_array;
my $error_flag;
my $error_line;
my $error_fname;
my $error_lname;

my $error_flag2=1;
my $error_line2;
my $error_fname2;
my $error_lname2;
my $i;
foreach my $player(@players_array){
    my @fields = split " ", $player;
    my $size2 = @fields;    

        for($i=2; $i<9; $i++){
    print "$fields[$i] \n";
            if (grep $_ =~ /^[a-zA-Z]+$/){

                my $errorflag2 = 1;
                $error_flag2 = $errorflag2;
                my $errorline2 = $player +1;
                $error_line2 = $errorline2;
                my $errorfname2 = $fields[0];
                $error_fname2 = $errorfname2;               
            }
        }

    if ($size2 ==  "9" ) {
        my $firstname = $fields[0];
        my $lastname = $fields[1];
        my $batting_average = ($fields[4]+$fields[5]+$fields[6]+$fields[7]) / $fields[3];
        my $slugging = ($fields[4]+($fields[5]*2)+($fields[6]*3)+($fields[7]*4)) / $fields[3];
        my $on_base_percent = ($fields[4]+$fields[5]+$fields[6]+$fields[7] +$fields[8]) / $fields[2];

        print "$firstname ";
        print "$lastname ";
        print "$batting_average ";
        print "$slugging ";
        print "$on_base_percent\n ";
    }
    else {
        my $errorflag = 1;
        $error_flag = $errorflag;
        my $errorline = $player +1;
        $error_line = $errorline;
        my $errorfname = $fields[0];
        $error_fname = $errorfname;
        my $errorlname = $fields[1];
        $error_lname = $errorlname;
    }

}
if ($error_flag == "1"){
        print "\n Line $error_line : ";
    print "$error_fname, ";
        print "$error_lname :";
    print "Line contains not enough data.\n";
}

if ($error_flag2 == "1"){
        print "\n Line $error_line2 : ";
        print "$error_fname2, ";

        print "Line contains bad data.\n";
}
10
  • Your use of grep is so wrong that this shouldn't compile. Commented Apr 9, 2018 at 6:08
  • @zdim so how do i fix it? Commented Apr 9, 2018 at 6:09
  • 1
    Why not start by showing the code you actually run to get that error? If we work with this we are merely guessing. Commented Apr 9, 2018 at 6:10
  • 1
    I suggest to check what you have that runs and prints the error you show. As for the basics of what you are asking, if (grep { /[a-z]/i } @fields[2..9]) { ... } Commented Apr 9, 2018 at 6:19
  • 2
    Re "ok i thought my full code might be too confusing but ill add it.", No, that's backwards!!! You should post the minimal, runnable code that demonstrates your problem. (See minimal reproducible example.) Commented Apr 9, 2018 at 6:27

2 Answers 2

5

OK, so the problem you've got here is that you're thinking of grep in Unix terms - a text based thing. It doesn't work like that in perl - it operates on a list.

Fortunately, this is pretty easy to handle in your case, because you can split your line into words.

Without your source data, this is hopefully a proof of concept:

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;


while ( <DATA> ) { 

   #split the current line on whitespace into an array. 
   #first two elements  get assigned to firstname lastname, and then the rest  
   #goes into @values
   my ( $firstname, $lastname, @values ) = split; #works on $_ implicitly.
   #check every element in @values, and test the regex 'non-digit' against it. 
   my @errors = grep { /\D/ } @values;
   #output any matches e.g. things that contained 'non-digits' anywhere. 
   print Dumper \@errors; 

   #an array in a scalar context evaluates as the number of elements. 
   #we need to use "scalar" here because print accepts list arguments. 
   print "There were ", scalar @errors, " errors\n";

}

__DATA__
bob hankerman 2039 3232 23 232 645 64x3 324

Or reducing down the logic:

#!/usr/bin/perl

use strict;
use warnings;

while ( <DATA> ) { 
   #note - we don't need to explicity specify 'scalar' here,
   #because assigning it to a scalar does that automatically. 

   #(split) splits the current line, and [2..8] skips the first two. 
   my $count_of_errors = grep { /\D/ } (split)[2..8];       
   print $count_of_errors;
}

__DATA__
bob hankerman 2039 3232 23 232 645 64x3 324
Sign up to request clarification or add additional context in comments.

Comments

0

First : You don't need to use "GREP", Simply you can match the string with "=~" in perl and you can print matched value with $&.

Second : You should use $_ if and only if there is not other variable used in the loop. There is already $i used in the loop, you can write the loop as :

for my $i (2..9) {
  print "$i\n";
}

or

foreach(2..9) {
  print "$_\n";
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.