在Perl中读取固定长度记录的最佳方式是什么?我知道,如同阅读文件:如何读取Perl中的固定长度记录?
ABCDE 302
DEFGC 876
我可以做
while (<FILE>) {
$key = substr($_, 0, 5);
$value = substr($_, 7, 3);
}
,但不是有没有办法与读取做到这一点/解压?
在Perl中读取固定长度记录的最佳方式是什么?我知道,如同阅读文件:如何读取Perl中的固定长度记录?
ABCDE 302
DEFGC 876
我可以做
while (<FILE>) {
$key = substr($_, 0, 5);
$value = substr($_, 7, 3);
}
,但不是有没有办法与读取做到这一点/解压?
更新:对于明确的答案,请参见下面乔纳森·莱弗勒的答案。
我不会用这只是两个字段(我会使用pack/unpack直接),但20个或50左右的领域我喜欢用Parse::FixedLength(但我有偏见)。例如。 (您的例子)(更新:也可以使用$ /和<>作为替代阅读($跳频,$ BUF,$ buf_length)...见下文):
use Parse::FixedLength;
my $pfl = Parse::FixedLength->new([qw(
key:5
blank:1
value:3
)]);
# Assuming trailing newline
# (or add newline to format above and remove "+ 1" below)
my $data_length = $pfl->length() + 1;
{
local $/ = \$data_length;
while(<FILE>) {
my $data = $pfl->parse($_);
print "$data->{key}:$data->{value}\n";
# or
print $data->key(), ":", $data->value(), "\n";
}
}
有一些使得pack/unpack更加“友好”的类似模块(参见Parse :: FixedLength的“See Also”部分)。
更新:哇,这是为了替代答案,而不是正式答案......好吧,既然它是什么,我应该包括一些乔纳森·莱弗勒的更直接的代码,这可能是你通常应做(见pack/unpack文档及以下乔纳森·莱弗勒的节点):
$_ = "ABCDE 302";
my($key, $blank, $value) = unpack "A5A1A3";
无论您的记录和字段是否为固定长度,如果这些字段由统一分隔符(例如空格或逗号)分隔,则可以比解压缩更容易使用拆分功能。
my ($field1, $field2) = split//;
查阅拆分文档。参数列表和分隔符格式的格式有很多有用的变化。
假设每条记录两块五字符字段的10个字符的记录:
open(my $fh, "<", $filename) or die $!;
while(read($fh, $buf, 10)) {
($field1, $field2) = unpack("A5 A5", $buf);
# ... do something with data ...
}
这里是另一种方式来做到这一点:
while (<FILE>)
{
chomp;
if (/^([A-Z]{5}) ([0-9]{3})$/)
{
$key = $1;
$value = $2;
}
}
如果任何字段值是小于固定宽度(虽然这在他的例子中不是这样),字符串会被分割为尾随空格,这是错误的。如果字段值长度全部相同,那么你是正确的,分隔和固定宽度之间没有区别 – 2009-01-02 21:00:22
这不是字段长度的问题。如果字段可以有很大的空白,你不能分割空白。这是固定长度字段的一个要点。 :) – 2009-01-03 00:32:11