Tom*_*han 7 command-line text-processing
我有一个很大的文本文件,其中每一行由三个数字组成,除了一些以主题标签 ( #)开头的注释行。我想验证非注释行是否按数字排序。有没有好的方法可以做到这一点?
我假设我必须使用类似的东西提取所有非注释行grep -ve \#- 但是我在哪里可以通过管道来验证输出是否已排序?
注意:我不是在寻找对文件进行排序的方法,而是要验证它是否已经排序(以验证我的程序的输出)。不幸的是,这并不像想要对文件的内容进行排序,或者(甚至更多)想要以特定顺序(例如,按字母顺序或按大小)列出文件夹的内容那么常见,因此 Google 有非常对我来说很少...
说明:文件中的数字是真实的,通常是指数形式。我希望它们按数字顺序排序,例如这意味着0.11000E+02 > 0.90000E+01 > 0.15000E-01.
如果它简化了任何,我知道如果文件与我想要的匹配,如果成对计算,前两列将被排序 - 换句话说,如果文件有效,则根本不必考虑第三列。
正式地,你可以这样表达:如果 x1和y1是一行的前两个数字,x2并且y2是另一行的前两个数字,那么(x1,y1)>(x2,y2) iff (x1>x2) || (x1==x2 && y1>y2)。(x1,y1)>(x2,y2)这里意味着带有x1和的行y1应该被认为更大,带有x2和y2,的行(x1,y1)应该出现在文件的下方 (x2,y2)。
示例输入: pastebin
我希望将上述文件视为已排序,但如果切换任意两行(不是注释行),则文件不再排序。请注意,行可以有前导空格。
#!/usr/bin/perl -w
use strict;
unless ( @ARGV == 1 && -f -r $ARGV[0] ) {
die "Expected single file argument!\n";
}
my %cols;
my $ind = 0;
while (<>) {
chomp;
next if /^\s*($|#)/;
( @{ $cols{col1} }[$ind], @{ $cols{col2} }[$ind], @{ $cols{col3} }[$ind] ) = split;
$ind++;
}
my @sorted1 = map { ${ $cols{col1} }[$_] } sort {
${ $cols{col1} }[$a] <=> ${ $cols{col1} }[$b] or
${ $cols{col2} }[$a] <=> ${ $cols{col2} }[$b] or
${ $cols{col3} }[$a] <=> ${ $cols{col3} }[$b]
} keys @{ $cols{col1} };
my @sorted2 = map { ${ $cols{col2} }[$_] } sort {
${ $cols{col1} }[$a] <=> ${ $cols{col1} }[$b] or
${ $cols{col2} }[$a] <=> ${ $cols{col2} }[$b] or
${ $cols{col3} }[$a] <=> ${ $cols{col3} }[$b]
} keys @{ $cols{col2} };
if ( "@sorted1" eq "@{ $cols{col1} }" and "@sorted2" eq "@{ $cols{col2} }") {
print "File is sorted!\n"
}
else { print "File is unsorted!\n" };
__END__
Run Code Online (Sandbox Code Playgroud)
如果列是:
X1 Y1 Z1
X2 Y2 Z2
Run Code Online (Sandbox Code Playgroud)
排序将是:
如果 (x1 > x2) 那么X1 Y1 Z1>X2 Y2 Z2
如果 (X1 == X2) && (Y1 > Y2) 那么X1 Y1 Z1>X2 Y2 Z2
要将更多列添加到排序顺序中,请复制前两列的模式。我希望这就是你所要求的。