1

タブで区切られたデータがあるとしましょう。

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

2番目の列ではなく、最初の列で並べ替えるだけで済みます。私はsortのドキュメントを読んでいますが、機能がないと思います。誰でも簡単な方法がありますか?

4

5 に答える 5

4

セクシーではありませんが、あなたの例では機能します:

 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
于 2013-02-08T01:06:46.303 に答える
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
于 2013-02-08T01:22:39.830 に答える
0

を使用する1つの方法があり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
于 2013-02-08T03:06:33.747 に答える
0

awk を使用した別の例を次に示します。

awk '{ a[ $1, ++b[$1] ]=$0 ; if(b[$1]>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 ステートメントに 3 つのループが存在すると、大きなファイルのパフォーマンスに影響を与える可能性があります。

于 2013-02-08T05:15:54.353 に答える
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 }'

「プロセス置換」には4.xを想定bashしていますが、組み込みawkのソートは使用していません(これは POSIX と比較したGNU拡張awkです)。明示的な一時ファイルを使用すると、プロセス置換なしでシェルで動作させることができます。

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

GNUawkと組み込みの並べ替え、または 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データセットにはソート条件が必要です。これは、Laura のエントリを Pater のエントリの前にソートします (省略した場合、これら 2 つのリストがインターリーブされます)。

于 2013-02-08T05:06:05.900 に答える