awk印刷コマンドで並べ替えを使用する方法


8

私が書いている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

awkスクリプトでこのsortコマンドを使用して、プレーヤーとその番号のみを並べ替える方法を教えてください。


3
回答についてのコメントを考えると、あなたの質問ではawkシェルスクリプトが混乱しているようです。ソーティングを呼び出すシェルスクリプトではなく、awkスクリプト内で並べ替えを実行したいようです。それが正しい場合は、質問を編集して、2つの「shell」を「awk」に置き換えてください。別のメモ:はい、awkには並べ替え機能がありますが、かなり複雑です。すべての行を配列に格納し、2番目のフィールドにキーを設定する必要があります。これをから抽出して、不可解な値に設定します。次に、配列を出力します。私はそこに行きません。xPROCINFO["sorted_in"]
zwets 2016年

1
つまり、の単純さを考えると、そこには行きません... | sort -k2,2
zwets 2016年

@zwets ...| sort -k2,2印刷する必要がある他の行がある場合、どのように実装しますか?編集した質問を確認してください。
KM142646 2016年

echoシェルからヘッダ行を-ing、次に実行awk | sortパイプライン。
zwets 2016年

回答:


12

| 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

残念ながら私はスクリプトを使用しており、sortコマンドは他の多くの出力とマッシュアップされます。の出力を{print x, $2}スクリプトコードで直接並べ替える方法はありますか?配管時にエラーが発生しますif(sum[x] > 500) {print x, $2} | sort -k2
KM142646 2016年

3
@KMoy:if(sum[x] > 500) {print x, $2}| sort -k2シェルコマンドですが、Awk コードです。もちろん、2つの言語は異なるため、この2つを混在させることはできません。代わりにsort、Awkコードスニペットを実行するAwkインタープリターの出力にコマンドを適用する必要があります。どういう意味かわからない場合は、質問全体を拡大してください。
David Foerster、2016年

1
あなたはシェルスクリプトを書いていますよね?次に、2つのオプションがあります。1.を実行し./my-script.sh | sort -k2ます。2. `|を追加 質問で指定された出力を生成するスクリプトの行に-k2`を並べ替えます。
Wayne_Yux

@Wayne_Yux元の質問に加えられた編集を確認してください。
KM142646 2016年

次に、おそらく@steeldriverからの回答が必要です
Wayne_Yux

9

gawkを使用した配列値とインデックスの並べ替えでsort説明されているように、(外部コマンドを介して結果をパイプする比較的単純な方法で)推奨しませんが、少なくとも最近のバージョンのGNU awk(少なくとも4.0 IIRC)でこれを実行できます。

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

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;
}

これでPROCINFO["sorted_in"]、@ zwetsのコメントに記載されている配列の並べ替え方法を使用できます

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

5

するために、sort空白文字のみで2番目のフィールド、使用キーを分離-k2,2

... | sort -k2,2

デフォルトでsortは、辞書順でソートを行います。

並べ替えキーの最後のフィールドに言及しない場合、つまり、使用しただけでは-k2、2番目以降のすべてのフィールドsortに従って、目的の結果が得られない場合があることに注意してください。

また、チェックしてくださいman sort


Wayneの投稿で私が必要なものについてのコメントをチェックしてください
KM142646

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

なぜ関数を定義するのですか?
zwets

@zwetsを使用すると、ループ制御構造を含む任意のコードの結果をパイプライン経由で簡単にフィードできます。必要ない場合もありますが、便利な一般的なパターンだと思います。これを実証するために、回答を編集します。
RedGrittyBrick 2016年

1

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

  • 2番目のフィールド(空白で区切られた)を印刷する場合は、次のように使用します。

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

    例えば:

    $cat>data.txt
    1 Kedar 20
    2 Amit 30
    3 Rahul 21
    ^C
    
    $awk '{print $2}' | sort
    Amit
    Kedar
    Rahul
    
  • 全体を印刷したいdata.txtが、列2でソートしたい場合:

    $awk '{print}'|sort -k2
    2 Amit 30
    1 Kedar 20
    3 Rahul 21
    

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

man sortより興味深い機能に使用できますsort


0

以下はどうですか:

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

テストすると機能します。


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

出力をファイルにソートするには:

print "Here are some players and their numbers, sorted by last name"
if(sum[x] > 500) {print x, $2 | "sort -k2,2 > sortedFile"}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.