代码之家  ›  专栏  ›  技术社区  ›  camh

按行的最后一个字段排序

  •  33
  • camh  · 技术社区  · 16 年前

    排序行列表的最简单方法是什么,按每行的最后一个字段排序?每行可以有不同数量的字段。

    sort -k -1
    

    是我想要的,但是sort(1)不采用负数从末尾而不是从开头选择字段。

    我也希望能够选择字段分隔符了。

    Edit:为问题添加一些特殊性:我要排序的列表是路径名列表。路径名的深度可以是任意的,因此字段的数目是可变的。我想按文件名组件排序。

    此附加信息可能会更改操作行以提取最后一个字段的方式(可以使用basename(1)),但不会更改排序要求。

    例如

    /a/b/c/10-foo
    /a/b/c/20-bar
    /a/b/c/50-baz
    /a/d/30-bob
    /a/e/f/g/h/01-do-this-first
    /a/e/f/g/h/99-local
    

    我希望这个列表按文件名排序,所有文件名都以数字开头,表示读取文件的顺序。

    我已经在下面添加了我的答案,这是我目前的做法。我曾希望有一种更简单的方法——也许是另一种排序工具——也许不需要操纵数据。

    10 回复  |  直到 16 年前
        1
  •  12
  •   Gabe Timothy Khouri    14 年前

    下面是一个Perl命令行(请注意,shell可能需要您转义 $

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

    只需将列表导入其中,或者,如果列表在文件中,则将文件名放在命令行的末尾。

    以下是示例输出:

    >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
    
        2
  •  20
  •   François Rousseau    13 年前
    awk '{print $NF,$0}' file | sort | cut -f2- -d' '
    

    1. 排序,使用用于排序的完整路径($0)解析重复的文件名
    2. 切割重复的第一个字段,f2-表示从第二个字段到最后一个字段
        3
  •  8
  •   ghostdog74    16 年前

    像这样的

    awk '{print $NF"|"$0}' file | sort -t"|" -k1 | awk -F"|" '{print $NF }'
    
        4
  •  3
  •   integer    16 年前

    perl中用于反转一行中字段顺序的一行:

    perl -lne 'print join " ", reverse split / /'
    

    / / 到 / +/ 所以它挤压空间。当然,您可以自由地使用任何正则表达式来拆分行。

        5
  •  2
  •   Philipp    16 年前

    我想唯一的解决办法就是 awk :

    1. 啊 .
    2. 将第一个字段再次放在末尾。
        6
  •  1
  •   camh    16 年前

    将行上的最后一个分隔符替换为列表中未出现的另一个分隔符,在第二个字段上使用该另一个分隔符作为排序(1)分隔符进行排序,然后还原分隔符更改。

    delim=/
    new_delim=" "
    cat $list \
    | sed "s|\(.*\)$delim|\1$new_delim|" \
    | sort -t"$new_delim" -k 2,2 \
    | sed "s|$new_delim|$delim|"
    

    问题是知道要使用的分隔符不在列表中。你可以对列表进行多次遍历,然后对一系列可能的分隔符进行grep,但这一切都相当糟糕——特别是当“对行的最后一个字段排序”的概念表达得如此简单,而解决方案却不是这样的时候。

    Edit:NUL是用于$new\delim的一个安全分隔符,因为它不能出现在文件名中,但我不知道如何将NUL字符放入bourne/POSIX shell脚本(不是bash)中,以及sort和sed是否能正确处理它。

        7
  •  0
  •   sarnold    16 年前
    #!/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
    

        8
  •  0
  •   commonpike    8 年前

    我希望这个列表按文件名排序,所有文件名都以数字开头 指示文件的读取顺序。

    find . | sed 's#.*/##' | sort
    

        9
  •  0
  •   Pykler    8 年前

    这是一个python的oneliner版本,注意它假设字段是整数,您可以根据需要更改它。

    echo file.txt | python3 -c 'import sys; list(map(sys.stdout.write, sorted(sys.stdin, key=lambda x: int(x.rsplit(" ", 1)[-1]))))'
    
        10
  •  0
  •   dardo82    7 年前
    | sed "s#(.*)/#\1"\\$'\x7F'\# \
    | sort -t\\$'\x7F' -k2,2 \
    | sed s\#\\$'\x7F'"#/#"
    

    仍然比sort(1)的简单负字段索引差很多,但是使用DEL字符作为分隔符在这种情况下不会引起任何问题。

    我也喜欢它的对称性。

        11
  •  -1
  •   Diego Sevilla    16 年前

    sort 允许您使用 -t

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

    ( $d 现在包含最后一个字段索引)。