1

我有这样的文件
FHEAD0000000001RTLG202106182103132021061430914
THEAD0000000002100 202106141001180000000310
TITEM
THEAD
TITEM
FTAIL

我想从 FHEAD 记录中提取商店和营业日期 文件中只有一个 FHEAD 记录

商店从位置 41 - 5digits ON FHEAD RECORD 营业日期从位置 33 - 8 digits ON FHEAD RECORD

我试过下面的命令
perl -lne ' ($s, $d) = (substr($_, 41, 5), substr($_, 33, 8)) if /FHEAD/; print "$ARGV,$s,$d"; ' $file

但它正在遍历文件中的所有记录并打印多行而不是一行我得到的输出为然而,应该只有一行
RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2 ,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119 .dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614 RTLOG_OMS_30914_20210618210313_71111119.dat.2,30914,20210614

4

3 回答 3

4

和正则表达式的substr答案很好,但是有一个经常被忽视的工具,叫做unpack.

格式说明符在文档中。是一个 ASCII 字符,后面的A数字是它的长度。所以,A5是接下来的五个 ASCII 字符。每个说明符产生一个列表项。A28跳过内容以到达正确的位置,然后A8获取日期并A5获取存储。

#!/usr/bin/perl
use v5.10;

while( <DATA> ) {
    next unless /\AFHEAD/;
    my( $header, $fill, $date, $store ) = unpack 'A5 A28 A8 A5', $_;

    say "DATE: $date";
    say "STORE: $store";
    last;
    }


__END__
FHEAD0000000001RTLG202106182103132021061430914
THEAD0000000002100 202106141001180000000310
TITEM
THEAD

这会产生:

DATE: 20210614
STORE: 30914

即使您不想使用pack,请注意我会做另一件事,您可以将其合并到其他答案中。跳过行,直到到达您想要的行,然后处理该行并终止循环。一旦你有了这条线,你就不需要看任何其他的线了。

作为一个单行,这可能是这样的,使用说明x符跳到一个绝对位置:

% perl -lne 'next unless /\AFHEAD/; print join "\t", unpack q(x33 A8 A5); last' file.txt
20210614    30914

当您处理更多字段时,这会变得更加有趣。

于 2021-06-23T17:24:47.513 回答
1

您的打印是无条件的。如果行匹配,您只想打印:

perl -lne ' print $ARGV,substr($_, 41, 5), substr($_, 33, 8) if /FHEAD/;' file
于 2021-06-22T16:06:39.227 回答
1

请查看以下命令是否产生所需的输出

 perl -lne 'print "date=$1 store=$2" if /FHEAD.{28}(.{8})(.{5})/' file

输出

date=20210614 store=30914
于 2021-06-22T16:27:03.433 回答