假设我有一些以制表符分隔的数据:
Peter 5
Joe 8
Peter 7
Peter 8
Joe 4
Laura 3
我希望按照第一列中名称出现的次数(最大到最小)对其进行排序 所以我们有Peter(3次出现)Joe(2次出现)和Laura(1次出现)。
Peter 5
Peter 7
Peter 8
Joe 8
Joe 4
Laura 3
它只需要按第一列排序,而不是第二列排序。我一直在阅读sort的文档,我认为它没有这个功能。任何人都有一个简单的方法?
答案 0 :(得分:3)
不性感但适合你的榜样:
awk 'NR==FNR{a[$1]++;next}{ print a[$1],$0}' file file|sort -nr|sed -r 's/[0-9]* //'
使用您的数据进行测试:
kent$ cat n.txt
Peter 5
Joe 8
Peter 7
Peter 8
Joe 4
Laura 3
kent$ awk 'NR==FNR{a[$1]++;next}{ print a[$1],$0}' n.txt n.txt|sort -nr|sed -r 's/[0-9]* //'
Peter 8
Peter 7
Peter 5
Joe 8
Joe 4
Laura 3
答案 1 :(得分:1)
这有效:
for person in $(awk '{print $1}' file.txt | sort | uniq -c | sort -dnr | awk '{print $2}');
do grep -e "^$person[[:space:]]" file.txt;
done
答案 2 :(得分:0)
这是使用GNU awk
的一种方式。像:
awk -f script.awk file
script.awk
的内容:
BEGIN {
FS="\t"
}
{
c[$1]++
r[$1] = (r[$1] ? r[$1] ORS : "") $0
}
END {
for (i in c) {
a[c[i],i] = i
}
n = asorti(a)
for (i=1;i<=n;i++) {
split(a[i], b, SUBSEP)
x[++j] = b[2]
}
for (i=n;i>=1;i--) {
print r[x[i]]
}
}
结果:
Peter 5
Peter 7
Peter 8
Joe 8
Joe 4
Laura 3
答案 3 :(得分:0)
这是一个令人惊讶的难以排序的标准。这段代码有效,但很难看:
data=${1:-data}
awk '{ print $1 }' $data |
sort |
uniq -c |
sort -k2 |
join -1 2 -2 2 -o 1.1,2.1,2.2,2.3 - <(awk '{ print NR, $0 }' $data | sort -k2) |
sort -k1,1nr -k3,3 -k2n |
awk 'BEGIN{OFS="\t"} { print $3, $4 }'
它假设bash
4.x代表'进程替换',但不使用内置于awk
的任何排序(与POSIX awk
相比,这是GNU扩展)。使用显式临时文件,可以使其在shell中工作而无需进程替换。
data=${1:-data} # File named on command line, or uses name 'data'
awk '{ print $1 }' $data | # List of names
sort | # Sorted list of names
uniq -c | # Count occurrences of each name
sort -k2 | # Sort in name order
join -1 2 -2 2 -o 1.1,2.1,2.2,2.3 - <(awk '{ print NR, $0 }' $data | sort -k2) |
# The process substitution numbers each record in sequence and sorts in name order
# The join matches the names (column 2) and outputs the frequency, record number, name, value
sort -k1,1nr -k3,3 -k2n | # Sort on frequency reversed, name, original line number
awk 'BEGIN{OFS="\t"} { print $3, $4 }' # Print name and value
将GNU awk
与内置排序或Perl或Python一起使用可能比这更好。
对于原始数据,输出为:
Peter 5
Peter 7
Peter 8
Joe 8
Joe 4
Laura 3
鉴于此数据的扩展版本:
Peter 5
Joe 8
Peter 7
Peter 8
Joe 4
Laura 3
Peter 50
Joe 80
Peter 70
Peter 80
Joe 40
Laura 30
Peter 700
Peter 800
Peter 7002
Peter 8002
Peter 7000
Peter 8000
Peter 7001
Peter 8001
Pater 50
Jae 80
Pater 70
Pater 80
Jae 40
Laura 30
输出结果为:
Peter 5
Peter 7
Peter 8
Peter 50
Peter 70
Peter 80
Peter 700
Peter 800
Peter 7002
Peter 8002
Peter 7000
Peter 8000
Peter 7001
Peter 8001
Joe 8
Joe 4
Joe 80
Joe 40
Laura 3
Laura 30
Laura 30
Pater 50
Pater 70
Pater 80
Jae 80
Jae 40
此数据集需要-k3,3
排序术语;它在Pater的条目之前对Laura的条目进行排序(当省略时,你会将这两个列表交错)。
答案 4 :(得分:0)
这是使用awk的另一个:
awk'{a [$ 1,++ b [$ 1]] = $ 0; if(b [$ 1]&gt; max)max = b [$ 1]}
END{ for(x=max;x>=1;x--) for( k in b ) if( a[k,x] ) for(y=1;y<=x;y++) { print a[k,y] delete a[k,y] } }' filename
使用gawk和POSIX awk可以正常工作。 END语句中存在三个循环可能会影响大文件的性能。