Perl简单的文件处理

时间:2016-03-25 10:59:42

标签: perl

这个程序的目的是读取一个文本文件,如下所示:

项目\ t \ t价格

apple \ t \ t 20

orange \ t \ t 50

lime \ t \ t 30

我使用拆分功能拆分这两列然后我应该对所有项目应用-25%的折扣并将其打印到新文件中。到目前为止我的代码完成了我想要的,但新文本文件有一个' 0'我在价格列中的最后一个数字下的值。如果我使用"使用警告"我也会遇到2个错误。这是:

在乘法* ...

中使用未初始化的值$ item

在连接(。)...

中使用未初始化的值$ item [0]

我还应该告诉计算的项目总数,但我得到的是5 1&#39;而不是5(<11111而不是5)

use strict;
use warnings;

my $filename  = 'shop.txt';
if (-e $filename){
    open (IN, $filename);
}
else{
    die "Can't open input file for reading: $!";
}
open (OUT,">","discount.txt") or die "Can't open output file for writing:    $!";

my $header = <IN>;

print OUT $header;

while (<IN>) {
    chomp;
    my @items = split(/\t\t/);
    foreach my $item ($items[1]){
        my $discount = $item * (0.75);
        print OUT "$items[0]\t\t$discount\n";
    }
}

4 个答案:

答案 0 :(得分:2)

这太复杂了,不清楚你在foreach循环中做了什么,而且你没有跳过空行。保持简单:

use warnings;
use strict;
use v5.10;

<>; # skip header
while(my $line = <>)
{
    chomp $line;
    next unless ($line);

    my ($title, $price ) = split /\s+/, $line;
    if( $title && defined $price )
    {
        $price *= 0.75;
        say "$title\t\t$price";
    }
}

并像

一样运行
perl script.pl <input.txt >output.txt

答案 1 :(得分:1)

use strict;
use warnings;

my $filename  = 'shop.txt';
if (-e $filename){
    open (IN, $filename);
}
else{
    die "Can't open input file for reading: $!";
}
open (OUT,">","discount.txt") or die "Can't open output file for writing:    $!";

my $header = <IN>;
my $item;
my $price;

print OUT $header;

while (<IN>) {
  chomp;
  ($item, $price) = split(/\t\t/);

  my $discount = $price*0.75;
  print OUT "$item $discount\n";

}

这应该有帮助! :)

答案 2 :(得分:1)

如果项目总数对您不是很重要:

$ perl -wane '$F[1] *= 0.75 if $. > 1; print join("\t", @F), "\n";' input.txt

输出:

Item    Price
apple   15
orange  37.5
lime    22.5

如果你真的需要总项数:

$ perl -we 'while (<>) { @F = split; if ($. > 1) { $F[1] *= 0.75; $i++ } print join("\t", @F), "\n"; } print "$i items\n";' input.txt

输出:

Item    Price
apple   15
orange  37.5
lime    22.5
3 items

答案 3 :(得分:0)

我会用这种方法

#!/usr/bin/perl

use strict;
use warnings;

my %items;
my $filename  = 'shop.txt';
my $discount = 'discount.txt';

open my $in, '<', $filename or die "Failed to open file! : $!\n";
open my $out, ">", $discount  or die "Can't open output file for writing:    $!";

print $out "Item\t\tPrice\n";
my $cnt = 0;
while (my $line = <$in>) {
    chomp $line;
    if (my ($item,$price) = $line =~ /(\w.+)\s+([0-9.]+)/){
        $price = $price * (0.75);
        print $out "$item\t\t$price\n";
        $items{$item} = $price;
        $cnt++;
    }
}
close($in);
close($out);

my $total = keys %items;

print "Total items - $total \n";
print "Total items - $cnt\n";

使用正则表达式捕获组捕获项目和价格(使用\ w。+,如果项目是2个单词,如苹果酱),这也将防止空行打印到文件。

我还对Item和Price标题进行了硬编码,如果你要使用一致的标题,这可能是一个好主意。

希望有所帮助

--- 更新 ----

我在脚本中添加了2个总计数的例子。第一种方法是使用散列并打印出散列大小,第二种方法是使用计数器。哈希选项很好,除非你的列表有两个相同的项目,在这种情况下,哈希的键将被覆盖,找到的最后一个项目具有相同的名称。计数器是一个简单的解决方案。