我有一个Perl脚本,它必须逐行读取文件。
文件中的行:
0060|9592014|A001-9592014-0060|82769|NOVARTIS PHARMA SERVICES AG BASEL|51671|NOVARTIS AG|A+|SWITZERLAND|Guarantees Issued|12/31/2016|12/31/2016|0|0|0|0|0|0|0|0|0|29014.0967835279993469339764885601502052|0||||0|1|550.3648|32541||.32|SUIG|OLEG|AAA||||||END|
我只需要32个字段,前32个字段。
open (PRISM, "$infile") or die "Can't open $infile\n";
while (my $file_line = <PRISM>)
{
last if ($file_line=~/^PRISMEXP/);
next if ($file_line=~/^(\s)*$/); # Skip blank lines
print "LINE: $file_line\n"; # This line doesn't print anything
my @field = (split /\|/, $file_line[0-32]);
print "$field[0]\n"; #This line doesn't print anything
}
正如您所看到的,这部分代码不会读取文件,也不会打印任何内容。为什么?我的错误在哪里?
答案 0 :(得分:3)
您WHILE
的位置应该while
。
此外,您的空行检查应该是=~
,而不是=
。
您的split
使用$file_line[0-32]
与$file_line[-32]
相同,这是@file_line
末尾的第32个元素,但您还没有设置在任何地方;我猜这应该是substr($file_line,0,32)
。
或者,如果您只想要前32个字段,则应该是:
my @field;
@field[0..31] = split /\|/, $file_line;
始终使用use strict; use warnings;
。它会捕获最后一个错误,也可能是第二个错误。
答案 1 :(得分:3)
以下是有关您的计划的一些注意事项,可帮助您提高成功率
总是 use strict
和use warnings
位于每个 Perl程序的顶部,如果您还没有这样做
使用词法文件句柄,例如my $prism_fh
,而不是像PRISM
不要将标量变量放在双引号内。充其量它没有任何区别,最坏的情况下你会得到一个完全不同的字符串
在检查$!
来电状态时,始终将die
变量放在open
字符串中。它会告诉你为什么打开失败。此外,perl会将源文件名和行号添加到die
的输出中,除非您在字符串末尾添加换行符,所以如果您想要,请不要这样做知道代码中发生错误的位置
从文件中读取时,通常最好使用默认变量$_
。许多运营商使用它作为默认参数,使代码更简洁整洁
不要忘记unless
。您可以使用next unless $file_line =~ /\S/
如果您没有chomp
输入行,则打印输出时无需在结尾处添加换行符
您需要split
行才能从输入中选择字段$file_line[0-32]
无效Perl
这是您重构的Perl代码,以便它打印前32个管道分隔字段。我希望很明显它需要一个use strict
和use warnings
的序言,并定义$infile
。
open my $prism_fh, '<', $infile or die qq{Can't open "$infile": $!\n};
while (<$prism_fh>) {
next unless /\S/;
last if /^PRISMEXP/;
chomp;
my @fields = (split /\|/);
print join('|', @fields[0 .. 31]), "\n";
}
<强>输出强>
0060|9592014|A001-9592014-0060|82769|NOVARTIS PHARMA SERVICES AG BASEL|51671|NOVARTIS AG|A+|SWITZERLAND|Guarantees Issued|12/31/2016|12/31/2016|0|0|0|0|0|0|0|0|0|29014.0967835279993469339764885601502052|0||||0|1|550.3648|32541||.32
<强>更新强>
您可以使用正则表达式来抓取前32个以管道分隔的字段,而不是拆分和重新组合,就像这样
while (<$prism_fh) {
next unless /\S/;
last if /^PRISMEXP/;
chomp;
print $1, "\n" if /^((?:[^|]*\|){31}[^|]*)/;
}
输出与上述程序的输出相同。
答案 2 :(得分:2)
由于这一行:
last if ($file_line=~/^PRISMEXP/);
如果$infile
的第一行以PRISMEXP开头,您将永远不会打印任何内容。
您还必须更改该行:
my @field = (split /\|/, $file_line[0-32]);
为:
my @field = (split /\|/, $file_line)[0..32];