对某些列中字段值相同的行组进行排序

对某些列中字段值相同的行组进行排序

我有一个像这样的文本文件:

1 bob A
1 jim B
1 Kate A
1 Nancy C
1 bill A
1 Jason A
2 James B
2 fill B
2 cake C
2 lucky C
2 Lucy A
2 lily B

如何按第 3 列对每个 1 和 2 组中的数据进行排序?输出应该是:

1 bob A
1 Kate A
1 bill A
1 Jason A
1 jim B
1 Nancy C
2 Lucy A
2 James B
2 fill B
2 lily B
2 cake C
2 lucky C

请注意,出现在输出Kate之前,因为它们在输入中按该顺序排列。bill

第 1 列的值很大,从 1、2 到 2000,所以我在比较行数时考虑 awk print 而不仅仅是等于某个值。

答案1

sort文件按第一列按数字排列,按第三列按字典顺序排列:

sort -s -k1n,1 -k3,3 file

注:-s是POSIX规范的扩展

答案2

如果您有 GNU 排序,-s请参阅@客人的解决方案,否则使用任何 cat+sort+cut:

$ cat -n file | sort -k2,2n -k4,4 -k1,1n | cut -f2-
1 bob A
1 Kate A
1 bill A
1 Jason A
1 jim B
1 Nancy C
2 Lucy A
2 James B
2 fill B
2 lily B
2 cake C
2 lucky C

答案3

收集数组中的每一行。当一行的第一个单词与前面的第一个单词不同时,打印按第三个单词排序的数组。当一个简单的东西sort就可以完成这项工作时,这可能有点过分了。以下内容不考虑与问题中显示的格式不同的输入文件。

呆呆地:

BEGIN {ors=ORS; ORS=""; PROCINFO["sorted_in"]="@ind_str_asc"}

$1!=r {
    output()
    delete a
    r=$1
}
{
    a[$3]=a[$3] $0 ors
}

END {
    output()
}

function output() {
    for (i in a)
        print a[i]
}

Python:

import fileinput, operator
r=''; a=[]
def out():
    for p in sorted(a,key=operator.itemgetter(2)):
        print(' '.join(p))

for line in fileinput.input():
    x = line.rstrip().split()
    if r!=x[0]:
        r=x[0]
        if a:
            out()
            del a[:]
    a.append(x)
out()

珀尔:

perl -lae 'sub out {foreach(sort keys %a) {print $a{$_}}} BEGIN {$ors=$\;$\=""}
    if ($F[0] ne $r) {$r=$F[0]; out; %a=()}
    $a{$F[2]}=$a{$F[2]}.$_.$ors; END{out}'

答案4

这是awk您想要的解决方案。 (具体来说,gawk [GNU  awk];这在 POSIX 中不起作用 awk。)

awk '
        function dump() {
                PROCINFO["sorted_in"] = "@ind_str_asc"
                for (arg3 in group) {
                        PROCINFO["sorted_in"] = "@ind_num_asc"
                        for (line_num in group[arg3]) {
                                print group[arg3][line_num]
                        }
                        PROCINFO["sorted_in"] = "@ind_str_asc"
                }
        }
        {
                if ($1 != saved_arg1) {
                        dump()
                        delete group
                        saved_arg1 = $1
                }
                group[$3][NR] = $0
        }
        END {
                dump()
        }
    '

主要工作从中间开始。对于每一行,如果它的$1值与我们最近看到的不同,则意味着我们正在进入一个新组。转储前一组数据(即将其写入输出),删除前一组保存的数据,然后记住新$1值。

然后,无论哪种情况,都将当前行添加到group数组中。这是一个二维数组,按$3值和NR (行号)索引。因此,例如,对于示例输入的前六行,我们得到

group["A"][1] = "1 bob A"
group["B"][2] = "1 jim B"
group["A"][3] = "1 Kate A"
group["C"][4] = "1 Nancy C"
group["A"][5] = "1 bill A"
group["A"][6] = "1 Jason A"

当我们在第 7 行看到$1 = 时2,我们调用该dump函数(在程序顶部定义)。  按顺序for (arg3 in group)设置arg3AB和。C然后, for arg3 =  A,循环for (line_num in group[arg3]) (即,按顺序for (line_num in group["A"])设置line_num 为 1356。所以我们打印出

1 bob A
1 Kate A
1 bill A
1 Jason A

其他值依此类推$3。其他值依此类推$1

相关内容