Finden Sie heraus, ob die Zeilen einer Datei sortiert sind

7

Ich habe eine große Textdatei, in der jede Zeile aus drei Zahlen besteht, mit Ausnahme einiger Kommentarzeilen, die alle mit einem Hashtag ( #) beginnen. Ich möchte überprüfen, ob die nicht kommentierten Zeilen numerisch sortiert sind. Gibt es eine gute Möglichkeit, dies zu tun?

Ich grep -ve \#gehe davon aus, dass ich alle nicht kommentierten Zeilen mit so etwas wie extrahieren muss - aber wo leite ich dies weiter, um zu überprüfen, ob die Ausgabe sortiert ist?

Hinweis: Ich suche nicht nach einer Möglichkeit, die Datei zu sortieren, sondern zu überprüfen, ob sie bereits sortiert ist (um die Ausgabe eines meiner Programme zu überprüfen). Leider ist dies nicht so häufig wie das Sortieren des Inhalts einer Datei oder (noch mehr) das Auflisten des Inhalts eines Ordners in einer bestimmten Reihenfolge (z. B. alphabetisch oder nach Größe) wenig für mich ...

Erläuterung: Die Zahlen in der Datei sind real, normalerweise in Exponentialform. Ich möchte, dass sie in numerischer Reihenfolge sortiert werden, was zum Beispiel bedeutet 0.11000E+02 > 0.90000E+01 > 0.15000E-01.

Wenn es etwas vereinfacht, weiß ich, dass wenn die Datei mit dem übereinstimmt, was ich will, die ersten beiden Spalten sortiert werden, wenn sie paarweise gezählt werden - mit anderen Worten, wenn die Datei gültig ist, muss die dritte Spalte überhaupt nicht berücksichtigt werden.

Formal können Sie es so ausdrücken: Wenn x1und y1die ersten beiden Zahlen in einer Zeile sind und x2und y2die ersten beiden Zahlen in einer anderen Zeile sind, dann (x1,y1)>(x2,y2) iff (x1>x2) || (x1==x2 && y1>y2) . (x1,y1)>(x2,y2)Dies bedeutet, dass die Zeile mit x1und y1als größer betrachtet werden sollte, die Zeile mit x2und y2und unten in der Datei (x1,y1)erscheinen sollte . (x2,y2)

Beispieleingabe: Pastebin
Ich erwarte, dass die obige Datei als sortiert betrachtet wird. Wenn jedoch zwei Zeilen (die keine Kommentarzeilen sind) vertauscht werden, wird die Datei nicht mehr sortiert. Beachten Sie, dass Zeilen führende Leerzeichen haben können.

Tomas Aschan
quelle

Antworten:

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__

Wenn die Spalten sind:

X1 Y1 Z1  
X2 Y2 Z2

Sortieren wird sein:

wenn (x1> x2) dann X1 Y1 Z1> X2 Y2 Z2
wenn (X1 == X2) && (Y1> Y2) dann X1 Y1 Z1>X2 Y2 Z2

Kopieren Sie das Muster für die ersten beiden, um der Sortierreihenfolge weitere Spalten hinzuzufügen. Ich hoffe, das haben Sie gefragt.

Basharat Sialvi
quelle
5

Ich hatte kürzlich diese Frage und habe sort - c from bash verwendet. Dadurch wird nur das Vorhandensein des ersten unsortierten Elements überprüft und gemeldet. Es kann mit anderen Flags kombiniert werden, um die Art der zu prüfenden Sortierung zu bestimmen (z. B. numerisch oder alphabetisch).

Markcelo
quelle