web-dev-qa-db-ja.com

大きなCSVファイルのインデックスの再作成

この役立つスレッド で答えを調べましたが、私の問題は十分に異なっているようで、良い答えを考えることができません(少なくともsedでは)。

次のような行を持つ大きなCSVファイル(200 GB以上)があります。

<alphanumerical_identifier>,<number>

どこ <alphanumerical_identifier>はファイル全体で一意です。 最初の列をインデックスに置き換える別のファイルを作成したいと思います。

<index>,<number>

次のようになります。

1, <number>
2, <number>
3, <number>

awkは、ファイル全体をメモリにロードせずに、増加するインデックスを生成できますか?

インデックスは単調に増加するため、インデックスを削除する方がよい場合があります。そのための解決策はそれとは異なりますか?つまり:

<number>
<number>
<number>
11

テストする端末の近くではありませんが、見過ごされがちなnlコマンドはどうでしょうか。何かのようなもの:

cut -f 2 -d , original.csv | nl -w 1 -p -s , > numbered.csv

13
bishop

ここにいくつかのアプローチがありますが、上記のcutおよびnlソリューションの速度に近づくものはありません。

  1. awk

    awk -F, '{$1=NR;print $1","$2;}' file.csv > newfile.csv
    
  2. Perl

    Perl -pe 's/[^,]+/$./' file.csv > newfile.csv
    

    または

    Perl -F, -ane '$F[0]=$.; print join ",", @F' file.csv
    
  3. シェル(ただし、200Gファイルにはお勧めしません。時間がかかります)

    i=1; while IFS=, read foo num; do 
            printf "%d,%s\n" $((i++)) $num; 
    done < file.csv > newfile.csv
    

上記のソリューションは、速度の順に並べ替えられています。私は自分のラップトップと40Mファイルでテストしましたが、シェルには2.2282(awk)、2.4555(1番目のPerl)、3.1825s(2番目のPerl)、そしてなんと48.6035秒かかりました。すでにお持ちの非常に賢いcutおよびnlソリューションは、0.6078秒で約4倍高速でした。

7
terdon