Bill Wang
Bill Wang

Reputation: 3

How would I sort the numbers without disturbing the format

My data file is like this:

* jsdklfjsldkfjlsdkfj
*.AW=351 Tb=sdf c=132  d=53135 s=sdlkfj
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 7
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 3
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 8
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 4
* jsdklfjsldkfjlsdkfj
*.AW=351 Tb=sdf c=132  d=53135 s=sdlkfj
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 7
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 3
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 8
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 4

The Perl code that I have so far is as follows:

open (my $file, "data.txt");
@data=<$file>;
close ($file);

open ($file, ">","data2.txt");
for (@data,undef) { 
if (defined && /^\:.*(\d+)\n/) { 
push @a, [$1,$_]; 
next }
print $file $_->[1] 
for sort { $a->[0] <=> $b->[0] } 
splice @a; 
print $file $_ if defined ;
} 
close ($file);

I'm not sure how to find the last number and rank it from small to large.

The same data sorted by rank is like this (Final format):

* jsdklfjsldkfjlsdkfj
*.AW=351 Tb=sdf c=132  d=53135 s=sdlkfj
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 3
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 4
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 7
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 8
* jsdklfjsldkfjlsdkfj
*.AW=351 Tb=sdf c=132  d=53135 s=sdlkfj
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 3
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 4
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 7
: A  CC=(111.153.781.36), DD=(111.153.781.36), (sdf_sdf) = 8

Upvotes: 0

Views: 105

Answers (2)

Shawn
Shawn

Reputation: 52529

Something like:

#!/usr/bin/env perl
use strict;
use warnings;
use autodie;

open my $data, "<", "data.txt";
open my $out, ">", "data2.txt";

my @lines;
while (my $line = <$data>) {
    if ($line =~ /^\* number/) {
        print $out $_->[1] for sort { $a->[0] <=> $b->[0] } @lines;
        @lines = ();
        print $out $line;
    } elsif ($line =~ /^\*/) {
        print $out $line;
    } elsif ($line =~ /^:/ && $line =~ /\s+(\S+)\s*$/) {
        push @lines, [$1, $line];
    } else {
        die "Unknown line! $line";
    }
}
close $data;
close $out;

The key bit is the print $out $_->[1] for sort { $a->[0] <=> $b->[0] } @lines; lines, which print out the actual lines after sorting by the number at the end.

Upvotes: 3

toolic
toolic

Reputation: 62154

Your regex is too greedy. This is less greedy:

if ( defined && /^\:.*=\s+(\S+)\n/ ) {

If you print the contents of @a before you print to your output file, you will see that it contains only the last digit (0), rather than the whole sci-not number (3.21533e-10), for example.

Upvotes: 0

Related Questions