Normal awk - 配列インデックスを簡単に並べ替え、選択した順序で出力します。

Normal awk - 配列インデックスを簡単に並べ替え、選択した順序で出力します。

[編集:明確にするには突然解決策と修正あいまいな「値」の代わりに「インデックス」をソートする必要があります(またはソートされた方法で出力)。

awkはしばしば数値を数えるか、値セットを配列に格納し、その値をインデックスとして使用します(awkのindexes_are_hashesメカニズムを使用)。

たとえば、私が出会った$2値の数と各値の発生頻度を知りたい場合は、次のようにします。

awk '
   ... several different treatments ...
   { count[$2]++ } 
   ... other treatments ...
   END { for(str in count) { 
           print "counted: " str " : " count[str] " times." 
           ... and other lines underneath, with additional infos ...
          }
       }
 '

問題は(GNUではないか、より良い)一般的なawk(および一般的なnawk)です。

  • [A] は「出会った」順に他の値を出力しません。
  • [B] 数字やアルファベット順にインデックスをナビゲートする簡単な方法も提供しません。

[A]の場合:それほど難しくありません。 「新しく見た」項目を索引付けする別の配列です。

問題は[B]についてです。簡単な呼び出しで他のインデックスの表示順序をどのように変更できますか?

(注:私はgnu awkが[B]に対して「簡単な」方法を持っていることを知っています:https://www.gnu.org/software/gawk/manual/html_node/Controlling-Array-Traversal.html...しかし、通常のawk / nawkで同様のことをする方法が欲しい! )

(例:表示されている別のインデックスを出力してソートし、[以前のawkで...]「何か」として再度読み込む必要があります(たとえば、別の配列が注文された_seen?)、それを使用してそれを表示する必要があります。見ることはあなたが選んだ順序で行わなければなりません。内部awk各インデックスの下に追加情報を出力する必要があることがよくあります。 awk以外の「ソート」はすべてを並べ替えます)

これまで、私はこれを行うための「公理的」断線(またはn線?)方法を見つけることができませんでした。

私は並べ替えで各値をファイルに出力するのに数行かかるパッチワークで終わりました。次に、ソートされたファイルを再度読み取り、各行を sorted_countindexes[n++] に順番に挿入し、for(i =0;i <= n;i++){ ...出力数[sorted_countindexes[n]]... }

通常のawk(またはnawk)の場合、ソートされた出力に基づくより良い/より単純な/より「公理的な」インデックスを歓迎します。

MCVE:以下は簡単な例です。インデックスをアルファベット順に出力するのが良いでしょう。

# create the 2 basic files to be parsed by the awk:
printf 'a b a a a c c d e s s s s e f s a e r r f\ng f r e d e z z c s d r\n' >fileA
printf 's f g r e d f g e z s d v f e z a d d g r f e a\ns d f e r\n'>fileB
# and the awk loop: It outputs in 'whatever order', I want in 'alphabetical order'
for f in file? ; do printf 'for file: %s: ' "$f"
  tr ' ' '\n' < "$f" | awk ' 
       { count[$0]++ } 
   END { for(str in count){ 
           printf("%s:%d ",str,count[str]) 
          }; print "" 
       } '
done
#this outputs:
for file: fileA: d:3 e:5 f:3 g:1 r:4 s:6 z:2 a:5 b:1 c:3
for file: fileB: d:5 e:5 f:5 g:3 r:3 s:3 v:1 z:2 a:2
# I'd like to have the letters outputted in alphabetical order instead!

ベストアンサー1

GNUを使用すると、「コプロセッシング」機能()を使用して双方向に対話でき、awkソートするデータを送信し、gawkを使用して結果を取得できますが、これはgawkに固有のものです。sortinfo gawk coprocprint |& "sort""sort" |& getline

配列を通るループ出会いの順番、録音できます出会いの順番配列を埋めるとき:

awk '
  !seen[$1]++ {sequence[n++] = $1}
  END {
    for (i = 0; i < n; i++)
      print sequence[i], seen[sequence[i]]
  }'

NETでソートアルゴリズムを実装することもできますawk。借りることもできgawkquicksort.awk借りることもできますよマニュアルで探す(ここでは、比較ルーチンのリテラル呼び出しで置き換えることができる別のGNU固有の機能である間接関数呼び出しを示します。)それは次のとおりです。

awk '
  function less_than(left, right) {
    return "" left <= "" right
  }
  function quicksort(data, left, right,   i, last)
  {
    if (left >= right)
      return

    quicksort_swap(data, left, int((left + right) / 2))
    last = left
    for (i = left + 1; i <= right; i++)
      if (less_than(data[i], data[left]))
        quicksort_swap(data, ++last, i)
    quicksort_swap(data, left, last)
    quicksort(data, left, last - 1)
    quicksort(data, last + 1, right)
  }
  function quicksort_swap(data, i, j,   temp)
  {
    temp = data[i]
    data[i] = data[j]
    data[j] = temp
  }

  {seen[$1]++}
  END {
    for (i in seen) keys[n++]=i
    quicksort(keys, 0, n-1)
    for (i = 0; i < n; i++)
      print keys[i], seen[keys[i]]
  }'

perl個人的に私はここで代わりに使用しますawk

おすすめ記事