У меня большой текстовый файл, где каждая строка состоит из трех чисел, за исключением нескольких строк комментариев, которые начинаются с хэштега (#
). Я хочу убедиться, что строки без комментариев отсортированы по номерам. Есть ли хороший способ сделать это?
Я предполагаю, что мне нужно извлечь все строки без комментариев с чем-то вроде 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)
в файл.
Пример ввода: 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__
Если столбцы:
X1 Y1 Z1
X2 Y2 Z2
Вид будет:
если (x1> x2) затем X1 Y1 Z1
> X2 Y2 Z2
если (X1 == X2) && (Y1> Y2) затем X1 Y1 Z1
> X2 Y2 Z2
Для добавления большего количества столбцов в порядок сортировки скопируйте шаблон для первых двух. Я надеюсь, что это - то, что Вы попросили.
У меня недавно был этот вопрос, и я использовал sort -c
из bash. Это будет только проверять наличие первого несортированного элемента и сообщать о нем и его строке. Его можно комбинировать с другими флагами для определения типа сортировки, который будет проверяться (например, числовой или буквенный).