使用文本文件的Perl代码

时间:2011-12-10 20:16:55

标签: linux perl command

为什么我的perl代码没有打印出来?我已经研究了一段时间了,我正在使用一个文本文件,它有大量不同的数据,我的数组中的每一个都用逗号分隔,这意味着它是一个列。

这是我的代码:

#!/usr/bin/perl

open (FILE, 'census2008.txt');

my @SumLevArray;
my @StNameArray;
my @CtyNameArray;
my @PopEstimateArary;
my @BirthsArray;
my @DeathsArray;

$i = 0;
$temp = 0;
$lowestBirthRates = 100000000;
$highestBirthRates = 0;
$size = 0;


while (<FILE>)
{
chomp;
($sumlev, $stname,$ctyname,$popestimate2008,$births2008,$deaths2008) = split(",");
push (@SumLevArray, $sumlev);
push (@StNameArray, $stname);
push (@CtyNameArray, $ctyname);
push (@PopEstimateArary, $popestimate2008);
push (@BirthsArray, $births2008);
push (@DeathsArray, $deaths2008);
}
$size = @BirthsArray;

while ($i < $size)
{
if($SumLevArray[$i] == " 040"){
$temp = $BirthsArray[$i]/$PopEstimateArary[$i]/541;
if(($lowestBirthRates > $temp) &&($temp > 0)){
$lowestBirthRates = $temp;
}
if($highestBirthRates < $temp){
$highestBirthRates = $temp;
}

}
$i = $i + 1;
}

print "\n";

print "Lowest birth rate in LOW-STATE: ";
print $lowestBirthRates;
print " per 541\n";

print "Highest birth rate in HIGH-STATE: ";
print $highestBirthRates;
print " per 541\n";

print "In Washington:\n";

print " Lowest birth rate in LOW-COUNTY County, WA: x.xxx per 541\n";

print " Highest birth rate in HIGH-COUNTY County, WA: x.xxx per 541\n";


close (FILE);
exit

8 个答案:

答案 0 :(得分:4)

帮助您的最佳工具是use strict; use warnings;。请将它放在您编写的每个脚本的顶部,因为这样可以节省大量时间来调试琐碎的问题。

在这里,有几个i缺少$ sigil。

另外,请考虑研究Perl数据结构食谱:perldoc perldsc。散列数组(技术上是hashrefs)是存储数据的数据结构的一种更具可扩展性的选择。

答案 1 :(得分:1)

尝试:

open (FILE, 'census2008.txt') or die $!;

如果你不知道,开放可能会失败。

答案 2 :(得分:1)

当您打印某些内容时,以换行符结束将导致它立即打印,否则文本将转到打印缓冲区但缓冲区不会被刷新。

答案 3 :(得分:1)

你应该解除stbout。

#!/usr/bin/perl

之后添加以下内容
$| = 1;

话虽如此,我还建议其他一些事情:

1。)至少use strict;(也建议use warnings

严格会强制您使用“我的”来声明您尚未执行此操作的变量。我不能告诉你我看过程序员搜索和搜索在开启严格检查时容易检测到的错误的次数。 (关于var名称的拼写错误是常见的)

2。)使用以下内容打开

open($FILE, "<", 'census2008.txt') || die("Cannot open file!");

这不仅会通知您是否无法打开文件(由于使用了die), 但是使用$FILE而不是原始文件句柄会导致文件自动关闭 超出范围。

答案 4 :(得分:1)

除了像其他人所建议的那样使用Text :: CSV之外,为了好玩,我已经重写了代码,因为我可能已经编写过了。它包括这里提出的许多建议以及我的一些个人风格选择。如果您对此有任何疑问,请询问。此外,如果您可以发布一些示例数据,我可以检查它是否有效。

#!/usr/bin/env perl

use strict;
use warnings;

my $lowestBirthRates = 100000000;
my $highestBirthRates = 0;

my $filename = 'census2008.txt';
open (my $fh, '<', $filename) or die "Cannot open $filename: $!";

my %data;

while (<$fh>) {
  chomp;
  my ($sumlev, $stname,$ctyname,$popestimate2008,$births2008,$deaths2008) = split(",");

  push (@{$data{SumLev}}, $sumlev);
  push (@{$data{StName}}, $stname);
  push (@{$data{CtyName}}, $ctyname);
  push (@{$data{PopEstimate}}, $popestimate2008);
  push (@{$data{Births}}, $births2008);
  push (@{$data{Deaths}}, $deaths2008);
}

my $i = 0;
my $size = @{$data{Births}};

while ($i < $size) {

  if ( $data{SumLev}[$i] eq " 040" ){
  #if ( $data{SumLev}[$i] == 40 ){

    my $temp = $data{Births}[$i] / $data{PopEstimate}[$i] / 541;

    if( $lowestBirthRates > $temp && $temp > 0 ){
      $lowestBirthRates = $temp;
    }

    if ( $highestBirthRates < $temp ){
      $highestBirthRates = $temp;
    }

  }

  $i++;
}

print <<REPORT;
Lowest birth rate in LOW-STATE: $lowestBirthRates per 541
Highest birth rate in HIGH-STATE: $highestBirthRates per 541
In Washington:
Lowest birth rate in LOW-COUNTY County, WA: x.xxx per 541
Highest birth rate in HIGH-COUNTY County, WA: x.xxx per 541
REPORT

如果您安装了Perl版本5.14或更高版本,则可以使用更清晰的语法,其中push可以直接引用,each可以提供相关索引以及价值。

#!/usr/bin/env perl

use strict;
use warnings;

use 5.14.0;

my $lowestBirthRates = 100000000;
my $highestBirthRates = 0;

my $filename = 'census2008.txt';
open (my $fh, '<', $filename) or die "Cannot open $filename: $!";

my %data = (
  SumLev => [],
  StName => [],
  CtyName => [],
  PopEstimate => [],
  Births => [],
  Deaths => [],
);

while (<$fh>) {
  chomp;
  my ($sumlev, $stname,$ctyname,$popestimate2008,$births2008,$deaths2008) = split(",");

  push ($data{SumLev}, $sumlev);
  push ($data{StName}, $stname);
  push ($data{CtyName}, $ctyname);
  push ($data{PopEstimate}, $popestimate2008);
  push ($data{Births}, $births2008);
  push ($data{Deaths}, $deaths2008);
}

while (my ($i, $births) = each $data{Births}) {

  if ( $data{SumLev}[$i] eq " 040" ){
  #if ( $data{SumLev}[$i] == 40 ){

    my $temp = $births / $data{PopEstimate}[$i] / 541;

    if( $lowestBirthRates > $temp && $temp > 0 ){
      $lowestBirthRates = $temp;
    }

    if ( $highestBirthRates < $temp ){
      $highestBirthRates = $temp;
    }

  }
}

print <<REPORT;
Lowest birth rate in LOW-STATE: $lowestBirthRates per 541
Highest birth rate in HIGH-STATE: $highestBirthRates per 541
In Washington:
Lowest birth rate in LOW-COUNTY County, WA: x.xxx per 541
Highest birth rate in HIGH-COUNTY County, WA: x.xxx per 541
REPORT

最后,这是一个使用Tie::Array::CSV的实现,我写的是能够像Perl中的2D数组一样使用CSV文件(即ArrayRefs数组)。它使用Text::CSV进行解析,使用Tie::File进行线路访问。这意味着您不需要像以前的示例那样将所有数据存储在内存中。

#!/usr/bin/env perl

use strict;
use warnings;

use Tie::Array::CSV;

my $lowestBirthRates = 100000000;
my $highestBirthRates = 0;

my $filename = 'census2008.txt';
tie my @data, 'Tie::Array::CSV', $filename
  or die "Cannot tie $filename: $!";


foreach my $row (@data) {
  my ($sumlev, $stname, $ctyname, $popest, $births, $deaths) = @$row;

  if ( $sumlev eq " 040" ){
  #if ( $sumlev == 40 ){

    my $temp = $births / $popest / 541;

    if( $lowestBirthRates > $temp && $temp > 0 ){
      $lowestBirthRates = $temp;
    }

    if ( $highestBirthRates < $temp ){
      $highestBirthRates = $temp;
    }

  }
}

print <<REPORT;
Lowest birth rate in LOW-STATE: $lowestBirthRates per 541
Highest birth rate in HIGH-STATE: $highestBirthRates per 541
In Washington:
Lowest birth rate in LOW-COUNTY County, WA: x.xxx per 541
Highest birth rate in HIGH-COUNTY County, WA: x.xxx per 541
REPORT

答案 5 :(得分:0)

尝试将您的第一行代码修改为:

#!/usr/bin/perl

use strict;
use warnings;

$| = 1; #

open (FILE, 'census2008.txt');

解决出现的错误/警告后,一切都应该没问题。

答案 6 :(得分:0)

要访问数组,请使用i而不是$ i作为索引。
除此之外,我不明白你想在while循环中做什么。

答案 7 :(得分:0)

该行存在问题:

if($SumLevArray[$i] == " 040"){

对于$SumLevArray[$i]的许多值,即"40", "040", " 00040 "

,此行评估为true

如果$SumLevArray[$i]是整数,则该行应为:

if($SumLevArray[$i] == 40){

如果$SumLevArray[$i]是一个字符串,则该行应为:

if($SumLevArray[$i] eq " 040"){