我有一个包含以下内容的格式文件
FIELD NO.,FIELD NAME,STARTING POSITION,ENDING POSITION,LENGTH,INDICATOR
1,SEQ_NO,1,11,11,N
2,CTR_REC_ID,12,14,3,N
3,CTR_SEQ_AMT,15,23,9,A
4,CTR_CONTRACT_NO,24,46,23,N
5,CTR_CONTRACT_AMT,47,59,13,A
6,CTR_TRACK_NO,60,62,3,N
该文件提供了有关每个字段的起始位置,结束位置和长度的详细信息。
我的脚本读取格式文件并将内容存储到数组中。然后逐行读取源文件,当格式文件中的指示符 A 时,将EBCDIC字符转换为合适的ASCII字符。
这是一个示例源文件,其索引显示了格式文件中列出的字符位置和字段。它不是数据文件的一部分。
1 2 3 4 5 6 7
1234567890123456789012345678901234567890123456789012345678901234567890
[ ][ ][ ][ ][ ][ ]
5|CTR00002173{09C00000000001 000000000201AE00
22|CTR00002243A52C00000000007 000000002358JF00
24|CTR00008456J52C00000000008 000000002465{F00
根据格式文件,第一行的CTR_SEQ_AMT
值为00002173{
。 {
必须转换为0
并用空格替换前导零,并将其设为十进制值(十进制(9,2))。
最终输出将如下所示:
5|CTR 217.3009C00000000001 20.11E00
22|CTR 224.3152C00000000007 -235.85F00
24|CTR -845.6552C00000000008 246.50F00
{ - > 0,A - > 1,J - > 5(将十进制值转换为负数)。
我使用Perl得到了上面的输出,但我的脚本性能不好。
我的源文件可以有一百万条记录。根据我的脚本,我有2个循环:一个用于读取格式文件并将数据存储到一个数组中,另一个用于逐行读取源文件并进行转换。因此,如果格式文件有10个要转换的字段,我的代码将遍历这些百万行10次。
不是有两个循环,我可以使用单个循环来读取格式文件,当字段的指示符为A时,对于特定字段,一次在所有行中执行以下操作:
目前我的代码有以下行来执行上述3个步骤。这一行包含源文件中的每一行。
$f_cnt = $start_pos - 1;
$dec_cnt = $array_length[$cnt] - 2;
$field = substr("$line", $end_pos -1, 1);
if ( $field eq '{' ) {
print "replacing { \n";
$x = substr($line, $f_cnt, $dec_cnt);
$x =~ s/^(0*)/' ' x length($1)/e;
substr($line, $f_cnt, $dec_cnt, "$x.");
substr($line, $end_pos, 1, "0") ;
}
答案 0 :(得分:0)
经过一些优化后,我有:
resolve: {
extensions: ['.ts', '.js'],
modules: [path.resolve(__dirname, "src"), "node_modules"]
},
可悲的是,我所取得的最快成就是:
my %ebcdic_fields;
while (my $line = <DATA>) {
my (undef, undef, $start, undef, $length, $indicator) = split /,/, $line;
next if $indicator !~ m/^A/;
$ebcdic_fields{$start-1} = $length - 2;
}
while (my $line = <>) {
while (my ($start, $length) = each %ebcdic_fields) {
my $fpos = $start + $length + 1;
my $before = substr ($line, $start, $length);
my $format = substr ($line, $fpos, 1);
my $trimed_before = $before + 0; # keep at least one 0 before the dot
if ($format ge 'J' and $format ne '{') {
substr ($line, $fpos, 1) =~ tr/}JKLMNOPQR/0123456789/;
substr ($line, $start, $length) = ' ' x ($length - length($trimed_before) - 2) . '-' . $trimed_before . '.';
} else {
substr ($line, $fpos, 1) =~ tr/{ABCDEFGHI/0123456789/;
substr ($line, $start, $length) = ' ' x ($length - length($trimed_before) - 1) . $trimed_before . '.';
}
}
print $line;
}
__DATA__
1,SEQ_NO,1,11,11,N
2,CTR_REC_ID,12,14,3,N
3,CTR_SEQ_AMT,15,23,9,A
4,CTR_CONTRACT_NO,24,46,23,N
5,CTR_CONTRACT_AMT,47,59,13,A
6,CTR_TRACK_NO,60,62,3,N