列の値の数を変更[閉じる]

列の値の数を変更[閉じる]

次のサンプルファイルがあります。

2931
7895
6688
7895
2931
2931
6688

この列と次のような他の列を含むファイルを生成したいと思います。

2931 1
7895 2
6688 3
7895 2
2931 1
2931 1
6688 3

答え1

それぞれの新しい種類のコンテンツに番号を付けてから、同じコンテンツを持つすべての行にその番号を表示する必要がありますか?

awk '
    { if ( !seen[$0]++ ) {
       ind++ ; n[$0]=ind
      }
    }

    { print $0, n[$0] }
'

必要なことをする

使用エドモートン提案は次のように簡略化され、「awk」に似ています。

awk '
   ! ($0 in n) { n[$0]=++ind }
               { print $0, n[$0] }
'

答え2

2番目の列が最初の列の各数字に対して一意の数字になりたいとします(質問では不明)。

$ awk '$2 = ( (k = key[$1]) ? k : key[$1] = ++n )' file
2931 1
7895 2
6688 3
7895 2
2931 1
2931 1
6688 3

nこれは、最も最近割り当てられた数字と関連配列の最初の列と結果の数字(「キー」)との間の関連性を追跡しますkey。変数は、k最初の列に数字がある場合に2回逆参照されないようにするための非常に小さな最適化です。key

論理:

$1$20 以外の場合、対応するキーが割り当てられます。 0 は初期化されておらず、$1以前に見たことがないことを意味します。 0の場合は、使用可能な次の番号をキーに割り当て、次にキーに割り当てます。$2

print式の結果はゼロではないため、明示的に何も作成する必要はありません。式の結果はゼロではないため、現在の(変更された)レコードを印刷する基本ジョブをトリガーします。

このコマンドのより一般的なバリエーションでは、入力データ内の列数に関係なく、行全体を値として使用し、最後に新しい列を追加します。

awk '$(NF+1) = ( (k = key[$0]) ? k : key[$0] = ++n )' file

対応する「長い表記」構文を使用してコードを綴ります。

awk '
{
    k = key[$0]

    if (k != 0)
        newval = k
    else
        newval = key[$0] = ++n

    print $0, newval
}' file

関連情報