web-dev-qa-db-ja.com

awk printコマンドでsortを使用する方法は?

私が書いているawkスクリプトにはいくつかのコマンドがあります。

print "Here are some players and their numbers, sorted by last name"
if(sum[x] > 500) {print x, $2}

どの出力:

Here are some players and their numbers, sorted by last name
Lebron James 23
Kevin Durant 35
Kobe Bryant 24
Blake Griffin 32
Dikembe Mutumbo 55

sortコマンドawkスクリプト内を使用して、プレーヤーとその番号のみをソートするにはどうすればよいですか?

8
KMoy

| sort -k2をコマンドに追加できます。これは、2番目の列に基づいてアルファベット順にソートされます。

例:

$ echo "Lebron James 23
Kevin Durant 35
Kobe Bryant 24
Blake Griffin 32
Dikembe Mutumbo 55" | sort -k2

結果として

Kobe Bryant 24
Kevin Durant 35
Blake Griffin 32
Lebron James 23
Dikembe Mutumbo 55
11
Wayne_Yux

私はそれをお勧めしませんが(外部sortコマンドを介して結果をパイピングすることは比較的簡単です)、少なくとも最近のバージョンのGNU awk(少なくとも4.0 IIRC)でこれを行うことができます gawkによる配列値とインデックスの並べ替え

インデックスがFirstname Lastnameである連想配列にデータがあると仮定して、これを実装する方法を次に示します。まず、インデックスを分割し、最初にLastnameで比較し、次に(タイブレーカーとして)Firstnameで比較するカスタム比較関数を定義する必要があります。

function mycmp(ia, va, ib, vb, sa, sb) {
  if(split(toupper(ia), sa) && split(toupper(ib), sb)) {
    if(sa[2] < sb[2]) return -1;
    else if (sa[2] > sb[2]) return 1;
    else {
      # compare first names
      if(sa[1] < sb[1]) return -1;
      else if (sa[1] > sb[1]) return 1;
      else return 0;
    }
  }
  else return 0;
}

これで、@ zwetsのコメントで言及されているPROCINFO["sorted_in"]配列ソート方法を使用できます

PROCINFO["sorted_in"] = "mycmp";
for(i in a) print i, a[i];

それを一緒に入れて

#!/usr/bin/gawk -f

function mycmp(ia, va, ib, vb, sa, sb) {
  if(split(toupper(ia), sa) && split(toupper(ib), sb)) {
    if(sa[2] < sb[2]) return -1;
    else if (sa[2] > sb[2]) return 1;
    else {
      # compare first names
      if(sa[1] < sb[1]) return -1;
      else if (sa[1] > sb[1]) return 1;
      else return 0;
    }
  }
  else return 0;
}

{
  a[$1" "$2] = $3;
}

END {
  PROCINFO["sorted_in"] = "mycmp";
  for(i in a) print i, a[i];
}

テスト:

$ ./namesort.awk yourfile
Kobe Bryant 24
Kevin Durant 35
Blake Griffin 32
Lebron James 23
Dikembe Mutumbo 55

旧バージョンのawkでは、代わりにLastname Firstnameでインデックス付けされたデータを保存し、従来のasortiでソートしてから、配列を走査するときにインデックスのフィールドを分割して交換するのが最善の策です印刷するには:

awk '
  {a[$2" "$1]=$3} 
  END {
    n=asorti(a,b); for (i=1;i<=n;i++) {split(b[i],s); print s[2], s[1], a[b[i]]}
}' yourfile
8
steeldriver

空白で区切られた2番目のフィールドのみでsortするには、キー-k2,2を使用します。

... | sort -k2,2

デフォルトでは、sortは辞書順にソートします。

ソートキーの最後のフィールドに言及しない場合、つまり-k2を使用する場合、すべてのフィールドに従ってsort 2番目から。

man sortも確認してください。

5
heemayl

データを並べ替えて印刷するには:

2番目のフィールド(空白区切り)を印刷したい場合は、これを使用します。

awk '{print $ 2}' data.txt | sort

例えば:

- -ターミナル - -

$cat>data.txt

1ケダー20

2アミット30

3ラーフル21

^ C

$awk '{print $2}' |sort

アミット

ケダール

ラーフル


Data.txt全体を印刷したいが、列2でソートしたい場合

それから

- - -ターミナル - - -

$awk '{print}'|sort -k2

2アミット30

1ケダー20

3ラーフル21

要件でこのロジックを使用します。

ソートのより興味深い機能にはmanソートを使用できます。!!!

UNIX/LINUXをお楽しみください!!

1

試してみる

awk -f myscript.awk | sort -k2

Myscript.awkには純粋にawkコマンドが含まれています。

実際のスクリプトがシェルスクリプトの場合、次のようないくつかのオプションがあります。

  • ソートを介してパイプ出力。 ./myscript.bash | sort -k2
  • スクリプト内の関数としてコードを書き換える
    の代わりに

    $ cat t1
    #!/bin/bash
    for i in 2 4 3 1 5;
    do
      echo $i
    done
    
    $ ./t1
    2
    4
    3
    1
    5
    

    行う

    $ cat t2
    #!/bin/bash
    function foo {
      for i in 2 4 3 1 5;
      do
        echo $i
      done
    }
    foo | sort
    
    $ ./t2
    1
    2
    3
    4
    5
    

ただし、関数を作成する代わりにdo ... done構造にソートを適用することもできます。

    do
       echo $i
    done | sort
1
RedGrittyBrick

以下はどうですか:

 awk 'BEGIN{str="1\n2\n3\n4"; system("echo -e \""str"\" | sort -r")}'

私がテストしたときに動作します。

0
Fei Wang