我有一个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";
}
答案 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";
}