我有一个像这样的文本文件:
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)
设置arg3
为A
、B
和。C
然后, for arg3
= A
,循环for (line_num in group[arg3])
(即,按顺序for (line_num in group["A"])
设置line_num
为 1
、3
、5
和6
。所以我们打印出
1 bob A
1 Kate A
1 bill A
1 Jason A
其他值依此类推$3
。其他值依此类推$1
。