Sorting on the last field of a line

后端 未结 11 988
暗喜
暗喜 2020-12-05 04:06

What is the simplest way to sort a list of lines, sorting on the last field of each line? Each line may have a variable number of fields.

Something like



        
相关标签:
11条回答
  • 2020-12-05 05:01

    sort allows you to specify the delimiter with the -t option, if I remember it well. To compute the last field, you can do something like counting the number of delimiters in a line and sum one. For instance something like this (assuming the ":" delimiter):

    d=`head -1 FILE | tr -cd :  | wc -c`
    d=`expr $d + 1`
    

    ($d now contains the last field index).

    0 讨论(0)
  • 2020-12-05 05:03
    awk '{print $NF,$0}' file | sort | cut -f2- -d' '
    

    Basically, this command does:

    1. Repeat the last field at the beginning, separated with a whitespace (default OFS)
    2. Sort, resolve the duplicated filenames using the full path ($0) for sorting
    3. Cut the repeated first field, f2- means from the second field to the last
    0 讨论(0)
  • 2020-12-05 05:07

    Here's a Perl command line (note that your shell may require you to escape the $s):

    perl -e "print sort {(split '/', $a)[-1] <=> (split '/', $b)[-1]} <>"
    

    Just pipe the list into it or, if the list is in a file, put the filename at the end of the command line.

    Note that this script does not actually change the data, so you don't have to be careful about what delimeter you use.

    Here's sample output:

    >perl -e "print sort {(split '/', $a)[-1] <=> (split '/', $b)[-1]} " files.txt
    /a/e/f/g/h/01-do-this-first
    /a/b/c/10-foo
    /a/b/c/20-bar
    /a/d/30-bob
    /a/b/c/50-baz
    /a/e/f/g/h/99-local
    
    0 讨论(0)
  • 2020-12-05 05:08

    Here is a python oneliner version, note that it assumes the field is integer, you can change that as needed.

    echo file.txt | python3 -c 'import sys; list(map(sys.stdout.write, sorted(sys.stdin, key=lambda x: int(x.rsplit(" ", 1)[-1]))))'
    
    0 讨论(0)
  • 2020-12-05 05:10
    #!/usr/bin/ruby
    
    f = ARGF.read
    lines = f.lines
    
    broken = lines.map {|l| l.split(/:/) }
    
    sorted = broken.sort {|a, b|
        a[-1] <=> b[-1]
    }
    
    fixed = sorted.map {|s| s.join(":") }
    
    puts fixed
    

    If all the answers involve perl or awk, might as well solve the whole thing in the scripting language. (Incidentally, I tried in Perl first and quickly remembered that I dislike Perl's lists-of-lists. I'd love to see a Perl guru's version.)

    0 讨论(0)
提交回复
热议问题