检查文件的行是否已排序

检查文件的行是否已排序

我有一个大型文本文件,其中每行由三个数字组成,除了几行注释行都以井号 ( #) 开头。我想验证非注释行是否按数字排序。有什么好方法可以做到这一点吗?

我假设我必须使用类似的方法提取所有非注释行grep -ve \#- 但是我应该在哪里将其传输到管道以验证输出是否已排序?

笔记:我是不是寻找一种方法来对文件进行排序,而是验证它已经已排序(用于验证我的程序的输出)。不幸的是,这并不像想要对文件内容进行排序那样常见,或者(甚至更常见)想要按特定顺序(例如按字母顺序或按大小)列出文件夹的内容,因此 Google 对我来说很少...

澄清:文件中的数字是实数,通常为指数形式。我希望它们按以下方式排序:数值顺序,例如意味着0.11000E+02 > 0.90000E+01 > 0.15000E-01

如果它简化了任何一个,我知道如果文件符合我想要的,前两列将按对计数进行排序 - 换句话说,如果文件有效,第三列根本不必考虑。

正式地,你可以这样表达:如果 x1y1是一行上的前两个数字,并且x2y2是另一行上的前两个数字,那么(x1,y1)>(x2,y2) 当且仅当 (x1>x2) || (x1==x2 && y1>y2)这里的意思是,和(x1,y1)>(x2,y2)的线应该被认为更大,和的线,和应该出现x1y1x2y2(x1,y1)以下 (x2,y2)在文件中。

示例输入: 粘贴箱
我期望上述文件被视为已排序,但如果任何两行(不是注释行)被交换,则文件不再排序。请注意,行可以有前导空格。

答案1

我最近遇到了这个问题,我使用了 bash 中的 sort --c。这将仅检查第一个未排序元素的存在并报告它。它可以与其他标志组合以决定要检查的排序类型(例如数字或字母)

答案2

#!/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__

如果列是:

X1 Y1 Z1  
X2 Y2 Z2

排序如下:

如果 (x1 > x2) 则X1 Y1 Z1>X2 Y2 Z2
如果 (X1 == X2) && (Y1 > Y2) 则X1 Y1 Z1>X2 Y2 Z2

要将更多列添加到排序顺序中,请复制前两列的模式。我希望这就是你想要的。

相关内容