如何读取Perl中的固定长度记录?
在Perl中读取固定长度记录的最佳方法是什么。我知道如何读取以下文件:如何读取Perl中的固定长度记录?,perl,fixed-length-record,Perl,Fixed Length Record,在Perl中读取固定长度记录的最佳方法是什么。我知道如何读取以下文件: ABCDE 302 DEFGC 876 我能行 while (<FILE>) { $key = substr($_, 0, 5); $value = substr($_, 7, 3); } while(){ $key=substr($\ 0,5); $value=substr($,7,3); } 但是,有没有一种方法可以通过读取/解包来实现这一点 my($key, $value) = unpac
ABCDE 302
DEFGC 876
我能行
while (<FILE>) {
$key = substr($_, 0, 5);
$value = substr($_, 7, 3);
}
while(){
$key=substr($\ 0,5);
$value=substr($,7,3);
}
但是,有没有一种方法可以通过读取/解包来实现这一点
my($key, $value) = unpack "A5 A3"; # Original, but slightly dubious
我们都需要在手册页面(尤其是手册页面)查看选项
由于A pack运算符删除了尾随空格,因此您的示例可以编码为:
my($key, $value) = unpack "A6A3";
或者(这是Perl,所以是TMTOWTDI):
1是可选的,但具有系统性和对称性。这样做的一个优点是,无论记录和字段的长度是否固定,都可以验证
$blank eq”“
,如果字段由统一的分隔符(如空格或逗号)分隔,则使用拆分功能比解包更容易
my ($field1, $field2) = split / /;
查找有关拆分的文档。在参数列表和分隔符模式的格式上有一些有用的变体。假设10个字符的记录,每个记录有两个5个字符的字段:
open(my $fh, "<", $filename) or die $!;
while(read($fh, $buf, 10)) {
($field1, $field2) = unpack("A5 A5", $buf);
# ... do something with data ...
}
open(my$fh),更新:有关最终答案,请参阅下面的Jonathan Leffler的答案
我不会只对两个字段(我会直接使用/使用)使用此选项,但我会对20或50个左右的字段使用此选项(但我有偏见)。例如(例如)(更新:您也可以使用$/和作为阅读($fh,$buf,$buf_length)的替代选项,请参见下文):
还有另一种方法:
while (<FILE>)
{
chomp;
if (/^([A-Z]{5}) ([0-9]{3})$/)
{
$key = $1;
$value = $2;
}
}
while()
{
咀嚼;
如果(/^([A-Z]{5})([0-9]{3})$/)
{
$key=$1;
$value=$2;
}
}
如果任何字段值小于固定宽度(尽管在他的示例中并非如此),字符串也将被拆分为尾随空格,这是错误的。如果字段值长度都相同,则您是正确的,分隔宽度和固定宽度之间没有区别。这不是字段长度的问题。如果字段可以有有效的空白,则不能拆分空白。这是固定长度的点之一字段:)这是最简单的答案
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";
}
}
$_ = "ABCDE 302";
my($key, $blank, $value) = unpack "A5A1A3";
while (<FILE>)
{
chomp;
if (/^([A-Z]{5}) ([0-9]{3})$/)
{
$key = $1;
$value = $2;
}
}