在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