我正在慢慢学习更多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|||
该文件看起来像这样,只会重复与上面类似的数据。输出将根据Text,LOV,Number 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";
}
}
我不知道我是否应该以不同的方式阅读文件,但任何建议或帮助都会很棒!感谢您提供的一切。
答案 0 :(得分: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
如果安装了Strawberry Perl或ActivePerl,这应该可以在Windows上正常工作。
如果您使用的是Linux或Mac,则需要执行此操作:
$ sudo cpan install Text::CSV
而且,您需要 root 密码。
安装完成后,如果您愿意,还可以安装Text::CSV_XS
。这使得Text :: CSV更快,特别是如果你有非常非常大的电子表格。
让我们一行一行:
以use
开头的前四行是应该在所有程序中的标准编译指示。 strict
将防止草率错误,warnings
将帮助您捕获其他类型的错误,例如使用不包含任何值的变量。
my $spreadsheet = Text::CSV->new
正在创建对象。这是您用来操作文件的内容。这有三个参数。 binary
允许多行数据(就像你拥有的那样)。 sep_char
表示您的分隔符不是逗号,而是|
符号。我不太确定eol
很重要 - 尤其是当我用<:crlf
打开文件时我处理Unix / Windows问题,这会将crlf
的实例转换为lf
1}}。
我打开文件并使用getline
方法读取我的行。这将读入您的多个长行,而无需计算行数或任何内容。
在:
my @columns = @{ $rows };
有点棘手。 Perl变量都基于单个值。当然你有哈希和数组,但它们是单个值的列表。有时,您需要将值作为一个集处理,而Perl使用References。 $rows
是指向我的列数组的指针。我解除引用引用并创建一个名为@columns
的真实数组。有关详细信息,请阅读Reference Tutorial。
$field =~ s/\n/, /g;
只是用逗号替换字段中新行的任何实例。
最后,我只需使用say
命令打印所有内容,然后使用join将我的行连接到一个字符串中,我可以打印出来并将它们|
分开。< / p>
注意我不需要计算和处理多行行。 Text::CSV
模块为我做了。它简短易懂,即使多个划线字段位于电子表格的中间,也能正常工作。