简体   繁体   中英

how to sort a file in bash whose lines are in a particular format?

all lines in file.txt are in the following format:

player16:level8|2200 Points
player99:level8|19000 Points
player23:level8|260 Points

how can I sort this file based on points? looking for the following output

player99:level8|19000 Points
player16:level8|2200 Points
player23:level8|260 Points

Any help would be greatly appreciated. Thank you.

sort is designed for this task

sort -t'|' -k2nr file

set the delimiter to | and sort by the second field numerical reverse order

You've tagged it as perl so I'll add a perlish answer.

perl's sort function lets you specify an arbitary comparison criteria, provided you return 'positive/negative/zero' depending on relative position. By default the <=> operator does this numerically, and the cmp operator does that alphabetically.

sort works by setting $a and $b to each element of a list in turn, and performing the comparison function for each pair

So for your scenario - we craft a function that regex matches each line, and extracts the points value:

sub sort_by_points {
   #$a and $b are provided by sort. 
   #we regex capture one or more numbers that are followed by "Points". 
   my ($a_points) = $a =~ m/(\d+) Points/;
   my ($b_points) = $b =~ m/(\d+) Points/;
   #we compare the points - note $b comes first, because we're sorting 
   #descending. 
   return $b_points <=> $a_points;
}

And then you use that function by calling sort with it.

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

sub sort_by_points {
   my ($a_points)= $a =~ m/(\d+) Points/;
   my ($b_points) = $b =~ m/(\d+) Points/;
   return $b_points <=> $a_points;
}

#reads from the special __DATA__ filehandle. 
chomp ( my @list = <DATA> ) ;
my @sorted_list = sort {sort_by_points} @list;
print join "\n", @sorted_list;

__DATA__
player16:level8|2200 Points
player99:level8|19000 Points
player23:level8|260 Points

For your purposes, you can use <> as your input, because that's the magic file handle - arguments on command line, or data piped through STDIN (might sound weird, but it's the same thing as sed/grep/awk do)

If you ask for Perl solution:

perl -F'\|' -e'push@a,[$_,$F[1]]}{print$_->[0]for sort{$b->[1]<=>$a->[1]}@a' file.txt

but using sort is far simpler

sort -t'|' -k2nr file.txt

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM