Descubra se as linhas de um arquivo estão classificadas

7

Eu tenho um arquivo de texto grande, onde cada linha consiste em três números, com exceção de algumas linhas de comentário que começam com uma hashtag ( # ). Quero verificar se as linhas não comentadas são classificadas numericamente. Existe uma boa maneira de fazer isso?

Eu suponho que eu tenha que extrair todas as linhas sem comentário com algo como grep -ve \# - mas onde eu canalizo isto para verificar se a saída está classificada?

Observação: não estou procurando uma maneira de classificar o arquivo, mas sim de verificar se ele está classificado (para verificar saída a saída de um programa meu). Infelizmente, isso não é tão comum quanto querer classificar o conteúdo de um arquivo, ou (ainda mais) querer listar o conteúdo de uma pasta em uma ordem específica (por ordem alfabética ou tamanho, por exemplo), então o Google tem muito pouco para mim ...

Esclarecimento: Os números no arquivo são reais, geralmente de forma exponencial. Quero que eles sejam classificados na ordem numérica , o que, por exemplo, significa que 0.11000E+02 > 0.90000E+01 > 0.15000E-01 .

Se isso simplificar, sei que se o arquivo corresponder ao que eu quero, as duas primeiras colunas serão classificadas se contadas em pares - em outras palavras, se o arquivo for válido, a terceira coluna não precisa ser considerada em tudo.

Formalmente, você pode expressá-lo assim: se x1 e y1 forem os dois primeiros números em uma linha, e x2 e y2 forem os dois primeiros números em outra linha, então (x1,y1)>(x2,y2) iff (x1>x2) || (x1==x2 && y1>y2) . (x1,y1)>(x2,y2) aqui significa que a linha com x1 e y1 deve ser considerada maior, a linha com x2 e y2 e (x1,y1) deve aparecer abaixo (x2,y2) em o arquivo.

Exemplo de entrada: pastebin
Espero que o arquivo acima seja considerado classificado, mas se quaisquer duas linhas (que não são linhas de comentários) forem trocadas, o arquivo não será mais classificado. Observe que as linhas podem ter espaços em branco iniciais.

    
por Tomas Aschan 17.04.2013 / 01:01

2 respostas

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__

Se as colunas forem:

X1 Y1 Z1  
X2 Y2 Z2

A classificação será:

se (x1 > x2) então X1 Y1 Z1 > X2 Y2 Z2
if (X1 == X2) & & (Y1 > Y2) então X1 Y1 Z1 > X2 Y2 Z2

Para adicionar mais colunas à ordem de classificação, copie o padrão para os dois primeiros. Espero que seja o que você pediu.

    
por Basharat Sialvi 17.04.2013 / 03:46
5

Recentemente tive essa pergunta e usei sort --c from bash. Isso só verificará a presença do primeiro elemento não classificado e o informará. Ele pode ser combinado com outros sinalizadores para decidir o tipo de classificação a ser verificado (por exemplo, numérico ou alfabético)

    
por markcelo 30.01.2015 / 11:17