bash 在bash中按多列排序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41231186/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 15:33:33  来源:igfitidea点击:

Sort by multiple columns in bash

linuxbashsortingreversealphabetical

提问by Alex

I have a file with 2 columns, "Name" and "Age", looking like this:

我有一个包含 2 列“名称”和“年龄”的文件,如下所示:

Alex,  15
Mary,  12
Alex,  28
Zoe,   16
Alex,  17

I will sort by the first column in alphabetical order, using sort -t ',' -k1,1 filename.txt, but if there are same names, I want the 2nd column to be sorted in the reversed way of how they were in the original file, like this:

我将按字母顺序按第一列排序,使用sort -t ',' -k1,1 filename.txt, 但如果有相同的名称,我希望第二列以它们在原始文件中的相反方式排序,如下所示:

Alex,  17
Alex,  28
Alex,  15
Mary,  12
Zoe,   17

How can I do this?

我怎样才能做到这一点?

回答by Tomá? ?íma

Read file from back, sort by the first column and -s to preserve order in case of same value

从后面读取文件,按第一列和 -s 排序以在相同值的情况下保留顺序

tac filename.txt | sort -k1,1 -s
...
Alex,  17
Alex,  28
Alex,  15
Mary,  12
Zoe,   16

回答by gct

Not sure why you'd want to do this! But you could do it in python pretty easily (doesn't preserve whitespace):

不知道你为什么要这样做!但是你可以很容易地在 python 中做到这一点(不保留空格):

import sys
entries    = [tuple(map(lambda x: x.strip(), line.strip().split(","))) for line in sys.stdin]
names,ages = zip(*entries)

def compare(a,b):
    res = cmp(a[0], b[0])
    if (res == 0):
        return -cmp(ages.index(a[1]), ages.index(b[1]))
    return res

print "\n".join("%s %s" % (name,age) for name,age in sorted(entries, cmp=compare))

回答by lqxyz

sort -t ',' -k1,1 -k2,2r filename.txt

or

或者

sort -t ',' -k1,1 -k2r,2 filename.txt

The output is:

输出是:

Alex,  28
Alex,  17
Alex,  15
Mary,  12
Zoe,   16

Explain: -tis to specify the field-separator, -kcan be used to specify the start and stop position of field, and we could add a single letter OPTSfor that field for ordering, for example rmeans to reverse the result of comparisons.

说明:-t是指定字段分隔符,-k可用于指定字段的开始和结束位置,我们可以OPTS为该字段添加单个字母进行排序,例如r表示将比较结果颠倒。

回答by piarston

Wops it seems I misunderstood your problem. I cannot find of a magic command, but a little script might do the job:

哇,看来我误解了你的问题。我找不到魔术命令,但一个小脚本可能会完成这项工作:

#! /bin/bash
declare names_sorted=$(cut -d, -f1 filename.txt | sort -k1,1 | uniq)
for name in $names_sorted ; do
    grep "$name," filename.txt | tac
done

Quick explanation:

快速解释:

  1. first we assemble the sorted list of names: $names_sorted.
  2. next (assuming the names do not contain white-spaces), we grep each name from the original list and revert that order with the command tac
  1. 首先我们组装名称的排序列表:$names_sorted
  2. 接下来(假设名称不包含空格),我们从原始列表中 grep 每个名称并使用命令恢复该顺序 tac

Hope it's what you wanted this time ;-)

希望这次是你想要的 ;-)

回答by piarston

This should gives what you want:

这应该给你想要的:

sort -k1,1 -k2,2 filename.txt