我有txt文件,每个行结构都是这样的:
P[containerVrsn:U(0)recordVrsn:U(0)size:U(212)ownGid:G[mdp:U(1090171666)**seqNo:U(81920)**]logicalDbNo:U(1)classVrsn:U(1)timeStamp:U(0)dbRecord:T[classNo:U(1064620)size:U(184)updateVersion:U(3)checksum:U(748981000)
必须根据seqNo(min到max)对文件行进行排序。序列号实际上可以是从零开始的任何数字。知道如何以有效的方式完成它?
答案 0 :(得分:2)
您可以使用Schwartzian Transform。
这是一个完成工作的小脚本:
#!/usr/bin/perl
use strict;
use warnings;
open my $fhi, '<', 'path/to/input/file' or die "Unable to open input file: $!";
my @lines = <$fhi>;
my @sorted = map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { my ($x) = $_ =~ /SeqNo:U\((\d+)/i; [$_, $x]; }
@lines;
open my $fho, '>', 'path/to/output/file' or die "Unable to open output file: $!";
print $fho $_ for @sorted;
答案 1 :(得分:2)
Toto's answer中建议的 Schwartzian变换可能是在这里对你的线进行排序的最快方法。但是你说你是一个Perl新手,而且我喜欢展示如何对这些行进行排序传统上。
Perl有一个sort
function,只需按字母顺序对列表进行排序。但是您可以提供自定义比较功能,让sort
使用您的函数来比较元素。在其操作期间sort
必须连续比较列表中的两个元素(=行),并决定哪一个更大或更小,或者它们是否相等。
如果您提供比较功能,sort
会使用参数$a
和$b
等两个元素来调用它。你不需要不能声明$a
和$b
,它们是神奇的,就在那里。您的比较功能可能如下所示:
sub by_seqNo
{
# extract the sequence number from $a and $b
my ($seqA) = ($a =~ /seqNo:U\((\d+)/);
my ($seqB) = ($b =~ /seqNo:U\((\d+)/);
# numerically compare the sequence numbers (returns -1/0/+1)
$seqA <=> $seqB;
}
前两行提取seqNo:U(
后的数字,并将其存储为$seqA
和$seqB
。第三行将这些序列号作为整数进行比较并返回结果。结合sort
函数,可以得到:
my @sorted = sort by_seqNo @lines;
Schwartzian变换(ST)比这个解决方案更快的原因是因为ST执行(昂贵的)操作,从每行的线路中提取一次seqNo。 &#34;传统&#34;另一方面,方法为每次比较提取两次seqNo。