Reputation: 59
I would like to sort files numerically using Perl script.
My files looks like below:
1:file1:filed2
3:filed1:field2
10:filed1:field2
4:field1:field2
7:field1:field2
I would like to display it as:
1:file1:filed2
3:filed1:field2
4:field1:field2
7:field1:field2
10:filed1:field2
Upvotes: 0
Views: 313
Reputation: 53478
The way sort
works in perl, is that it works through your list, setting each element to $a
and $b
- then testing those. By default, it uses cmp
which is an alphanumeric sort.
You've also got <=>
which is a numeric sort, and the kind you're looking for. (Alpha sorts 10
ahead of 2
).
So - all we need do is extract the numeric value of your key. There's a number of ways you could do this - the obvious being to take a subroutine that temporarily copies the variables:
#!/usr/bin/env perl
use strict;
use warnings;
sub compare_first_num {
my ( $a1 ) = split ( /:/, $a );
my ( $b1 ) = split ( /:/, $b );
return $a1 <=> $b1;
}
print sort compare_first_num <>;
This uses <>
- the magic filehandle - to read STDIN
or files specified on command line.
Or alternatively, in newer perls (5.16+):
print sort { $a =~ s/:.*//r <=> $b =~ s/:.*//r } <>;
We use the 'substitute-and-return' operation to compare just the substrings we're interested in. (Numerically).
Upvotes: 2
Reputation: 4709
For simple and fast solution, use Sort::Key::Natural (fast natural sorting) module:
use warnings;
use strict;
use Sort::Key::Natural qw( natsort );
open my $fh, "<", "file.txt" or die $!;
my @files = natsort <$fh>;
close $fh;
print @files;
Output:
1:file1:filed2
3:filed1:field2
4:field1:field2
7:field1:field2
10:filed1:field2
Upvotes: 1
Reputation: 6578
Split on :
and store in a hash of arrays. Then you can sort and print out the hash keys:
my %data;
while(<DATA>){
my @field = split(/:/);
$data{$field[0]} = [@field[1..2]];
}
print join (':', $_, @{$data{$_}}) for sort { $a <=> $b } keys %data;
print "\n";
1:file1:filed2
3:filed1:field2
4:field1:field2
7:field1:field2
10:filed1:field2
Upvotes: 1