我有一个大型文本文件,其中每行由三个数字组成,除了几行注释行都以井号 ( #
) 开头。我想验证非注释行是否按数字排序。有什么好方法可以做到这一点吗?
我假设我必须使用类似的方法提取所有非注释行grep -ve \#
- 但是我应该在哪里将其传输到管道以验证输出是否已排序?
笔记:我是不是寻找一种方法来对文件进行排序,而是验证它已经已排序(用于验证我的程序的输出)。不幸的是,这并不像想要对文件内容进行排序那样常见,或者(甚至更常见)想要按特定顺序(例如按字母顺序或按大小)列出文件夹的内容,因此 Google 对我来说很少...
澄清:文件中的数字是实数,通常为指数形式。我希望它们按以下方式排序:数值顺序,例如意味着0.11000E+02 > 0.90000E+01 > 0.15000E-01
。
如果它简化了任何一个,我知道如果文件符合我想要的,前两列将按对计数进行排序 - 换句话说,如果文件有效,第三列根本不必考虑。
正式地,你可以这样表达:如果 x1
和y1
是一行上的前两个数字,并且x2
和y2
是另一行上的前两个数字,那么(x1,y1)>(x2,y2)
当且仅当 (x1>x2) || (x1==x2 && y1>y2)
这里的意思是,和(x1,y1)>(x2,y2)
的线应该被认为更大,和的线,和应该出现x1
y1
x2
y2
(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
要将更多列添加到排序顺序中,请复制前两列的模式。我希望这就是你想要的。