循环遍历数组元素以查找字符perl

时间:2018-04-09 05:59:50

标签: arrays perl scope

我有一个perl数组,我只想循环遍历元素2-8。

元素仅用于包含数字,因此如果这些元素中的任何一个包含字母,我想设置error flag = 1,以及其他一些变量。

我有2个错误标志变量的原因是由于循环中的范围规则。

fields是一个数组,我是通过“”键拆分另一个不相关的数组而创建的。

所以,当我尝试从循环外部打印error_line2, error_fname2时,我得到了这个:

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

我不知道为什么,因为我已经在循环中初始化了值并在循环外创建了变量。 我不确定我是否正在循环找到正确的字符,所以它没有设置error_flag2 = 1

示例行

bob hankerman 2039 3232 23 232 645 64x3 324

因为元素7的字母是'x',所以我希望将标志设置为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";
}

2 个答案:

答案 0 :(得分:5)

好的,所以你在这里遇到的问题是你在Unix术语中考虑grep - 基于文本的东西。它在perl中不起作用 - 它在列表上运行。

幸运的是,在您的情况下,这很容易处理,因为您可以split将您的行转换为单词。

如果没有您的源数据,这有望成为概念证明:

#!/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

或减少逻辑:

#!/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

答案 1 :(得分:0)

首先:你不需要使用“GREP”,只需在perl中将字符串与“=〜”匹配,就可以用$&amp;打印匹配的值。

第二:当且仅当循环中没有使用其他变量时,才应使用$ _。循环中已经使用了$ i,您可以将循环写为:

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

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