2013-07-16 37 views
1

我正在慢慢学习更多的PERL,并且需要一些帮助来解决我正面临的问题。我有一个以csv格式给出的excel电子表格的输入文件。在电子表格中,如果行中的一个单元格值为“LOV”,则它们将合并单元格并给出值列表。我需要抓住与该LOV一起出现的下一个X行,然后将该LOV与同一行中的其他值一起输出到单行中。所以这里是输入文件的样子:基于特定行中的值获取多行输入文件

Intro |Input|Middle |PPP|Requirement|Manual|Text||| 
Intro |Input|END |PPP|Design|Manual|LOV|"Ancestory 
Red 
Blue 
Purple 
Orange 
Yellow"|| 
Intro |Output|END |PPP|Design|Automatic|Number||| 

该文件看起来像这样,并将重复类似于上面的数据。输出将根据文本,LOV,编号ETC放在不同的文件中。我需要得到的LOV输出如下所示:

Intro |END |LOV|"Ancestory Red Blue Purple Orange Yellow"|| 

我完全失去了如何解决这个问题。我可以使用数组来获取引用内的下一行吗?我可以抓住所有其他线路,但迄今为止,这是我的逻辑看起来像。

my @LOV; 
while(<file1>){ 

      my($line) = $_; 
      chomp $line; 
      if $line == "LOV" 
      { 

       push @LOV, $_; 
       while (<file1>) 
       { 
        last if /^$/; 
        push @LOV, $_; 
       }      
        print file2 "$output\n"; 
      } 
      else 
      { 


       if ("NUMBER") 
       { 
        print file3"output"; 
       } 
       else if ("Text") 
       { 
        print file4"output"; 
       } 

      } 

我不知道我是否应该以不同的方式阅读文件,但任何建议或帮助将是伟大的!谢谢你提供的任何东西。

回答

4

只是好奇。你用什么书来学习Perl?

你的编码风格是方式,过时的方式。您不是第一个学习Perl的人,并且使用的语法风格始于20世纪80年代后期,所以我只是好奇人们用来学习Perl的市场上的书(或网页)。

有关Perl的奇妙之处之一是它有很多模块可以处理你想要的大部分内容。在这种情况下,你需要使用Text::CSV模块与他们的嵌入式NL读到那篇文章的时候,会做所有繁重的你:

use warnings; 
use strict; 
use autodie; 
use feature qw(say); 

use Text::CSV; 

my $spreadsheet = Text::CSV->new (
    { 
     binary  => 1, 
     sep_char => "|", 
     eol   => $/, 
    } 
); 
open my $file, "<:crlf", "text.csv"; 

while (my $row = $spreadsheet->getline($file)) { 
    my @columns = @{ $row }; 
    for my $field (@columns) { 
     $field =~ s/\n/, /g; 
    } 
    say join " | ", @columns; 
} 

这会打印出:

Intro | Input | Middle | PPP | Requirement | Manual | Text | | | 
Intro | Input | END | PPP | Design | Manual | LOV | Ancestory, Red, Blue, Purple, Orange, Yellow | | 
Intro | Output | END | PPP | Design | Automatic | Number | | | 

不幸,它采用面向对象符号它可以是一个有点混乱,但我会努力的点点打破这种分离位:

首先,你可能需要安装Text::CSV。你可以做到这一点与下面的命令:

$ cpan install Text::CSV 

这应该在Windows正常工作,如果你有安装Strawberry Perl或的ActivePerl。

如果你在Linux或Mac上,你需要这样做:

$ sudo cpan install Text::CSV 

而且,你需要你的密码。

安装完成后,如果您愿意,也可以安装Text::CSV_XS。这使得Text :: CSV更快,特别是如果你真的有非常大的电子表格。

让我们走这条线,由线:

前四行与use开始是标准的编译指示,应在所有程序。 strict将防范马虎的错误,warnings将帮助您捕捉其他类型的错误,如使用不包含任何值的变量。

my $spreadsheet = Text::CSV->new正在创建一个对象。这是你将用来操作你的文件。这有三个参数。 binary允许多个内衬数据(如你所拥有的)。 sep_char表示您的分隔符不是逗号,而是|符号。 eol我不太确定非常重要 - 尤其是当我使用<:crlf打开文件时处理Unix/Windows问题,该文件会将crlf的实例转换为lf的实例。

我打开我的文件并使用getline方法读取我的行。这将读取你的多行,而不必计算行数或任何东西。

的:

my @columns = @{ $rows }; 

是有点麻烦。 Perl变量都基于单个值。当然你有散列和数组,但它们是单值列表。有时候,你需要将值作为一组来处理,而Perl使用引用。 $rows是指向我的列的数组的指针。我是取消引用的参考并创建了一个名为@columns的真实数组。阅读Reference Tutorial了解更多信息。

$field =~ s/\n/, /g;只是用逗号代替新行的任何实例。

最后,我只是使用say命令和使用join将所有行连接到一个单独的字符串中打印出来,并将它们分开打印出来。

注意我不需要计算和处理多行的行。 Text::CSV模块为我做。它很简短,易于理解,并且即使多行字段位于电子表格中间也可以工作。

+0

我觉得我需要一口白兰地酒,也许在读完这个答案后小睡一会儿。优秀! –

+0

我一直在飞行中学习。没有书,也没有真正的老师只是在网上教程和通过其他人。我可以告诉现在我的原始代码有多糟糕。谢谢你的回答,这远远超过我的预期。有没有你可能推荐的书? – user1258104

+0

@ user1258104 - 一个开始的好地方:http://modernperl.net –