2番目のファイルキーに基づいて最初のファイル(csv)をソートする方法

2番目のファイルキーに基づいて最初のファイル(csv)をソートする方法

2番目のファイルキーに基づいて最初の列を使用して最初のファイルをソートするソリューションを見つけようとしています。

最初のファイルの例(file1.csv)

COLUMN1 COlUMN2
apple fruit
dog animal
cat animal
cow animal

2番目のファイルの例(sort_keys.txt)

cat
dog
apple
cow

期待される出力(sorted.txt)

COLUMN1 COlUMN2
cat animal
dog animal
apple fruit
cow animal

これまで役立つ sort コマンドと awk コマンドを見つけましたが、うまくいくコードはありません。

$> awk 'NR==FNR{o[FNR]=$1; next} {t[$1]=$0} END{for(x=1; x<=FNR; x++){y=o[x]; print t[y]}}' sort_key.txt file1.csv

しかし、コマンドが期待どおりに機能しないため、専門家のアドバイスが必要です。 PS 私はLinuxコマンドの知識を持っていますが、これは非常に具体的であり、実装方法を知りません。

どんな助けやアドバイスにも感謝します。

答え1

$ awk 'NR==1; NR==FNR{a[$1]=$2; next} {print $1, a[$1]}' file1 sort_keys.txt
COLUMN1 COlUMN2
cat animal
dog animal
apple fruit
cow animal

答え2

GNU awk(別名)があれば、カスタムgawkソート機能を定義して使用できます。

たとえば、PROCINFOGNU awk> 4.0の配列反復関数を想定すると、次のようになります。

$ gawk '
  function mysort(ia,va,ib,vb){return o[ia] - o[ib]}

  NR==FNR{o[$1]=FNR; next}      # map keys to numerical order

  FNR==1{print; next}           # print + skip the header line
  {a[$1]=$0}

  END{
    PROCINFO["sorted_in"] = "mysort"
    for(i in a) print a[i]
  }
' sort_key.txt file1.csv
COLUMN1 COlUMN2
cat animal
dog animal
apple fruit
cow animal

(以前のGNU awksではasorti

答え3

データがそれほど大きくない場合、二次複雑さを持つ簡単なソリューションは次のとおりです。

cat sort_keys.txt | while read key ; do egrep "^$key " file1.csv ; done

ヘッダーを追加/削除するには、head必要に応じてコマンドを追加します。tail

答え4

あなたはそれを使用することができますjoin。からman join

同じ結合フィールドを持つ各入力行ペアに対して、標準出力に1行を書き込みます。デフォルトの結合フィールドは最初にスペースで区切られます。

最初の行はソートしてはいけません。

全長DR:

head -n 1 file1.csv; join -1 2 <(cat -n sort_keys.txt | sort -k 2) <(tail -n +2 file1.csv | sort) | sort -n -k 2 | awk '{ print $1, $3 }'仕事をします。

説明する

基本的に我々は:

  • file1.csv の最初の行を抽出します。
  • 最初のフィールドで sort_keys を使用して file1.csv の残りの部分をリンクします。
  • sort_keys の順序で結果を並べ替える

また、joinファイルを並べ替える必要があります。

これは私たちを次に導きます:

  • 最初の入力としてsort_keysファイル(前のフィールドで)に番号を付け(最後にこの元の順序を使用できるように)、2番目のフィールドを並べ替えます。

cat -n sort_keys.txt | sort -k 2

  3 apple
  1 cat
  4 cow
  2 dog
  • 2番目の入力としてcsvファイルをインポートし、最初の行をスキップして最初のフィールドでソートします。

tail -n +2 file1.csv | sort

 apple fruit
 cat animal
 cow animal
 dog animal
  • その後、最初のプロセスの2番目のフィールド()を使用して-1 2それらを結合できます。

join -1 2 <(cat -n sort_keys.txt | sort -k 2) <(tail -n +2 file1.csv | sort)

 apple 3 fruit
 cat 1 animal
 cow 4 animal
 dog 2 animal
  • これで、結合結果を2番目のフィールドの数字で並べ替えることができます(sort_keysが9項目を超える場合)、最初と3番目のフィールドのみを保持します。

「... | sort -n -k 2 '{$ 1、$ 3印刷}」

 cat animal
 dog animal
 apple fruit
 cow animal
  • 最後に、これをfile1.csvの最初の行の前に追加します。

head -n 1 file1.csv; join -1 2 <(cat -n sort_keys.txt | sort -k 2) <(tail -n +2 file1.csv | sort) | sort -n -k 2 | awk '{ print $1, $3 }'

 COLUMN1 COlUMN2
 cat animal
 dog animal
 apple fruit
 cow animal

さらに進む

実際のデータに応じて、フィールド番号とフィールド区切り記号を調整する必要があります。

キーがsort_keysにないデータ行、またはsort_keysにそのデータ行がない行を保持したい場合もあります(-a結合オプションを参照)。

自由に試してみてくださいjoin

関連情報