
これはあなたのフォローアップの質問です。大容量CSVファイル(90 GB)をソート中にディスククォータを超えました。。これで、file1.csvやfile2.csvなど、2つのCSVファイルが並べ替えられます。各CSVファイルには、次の4つの列があります。
ファイル1:
ID Date Feature Value
01 0501 PRCP 150
01 0502 PRCP 120
02 0501 ARMS 5.6
02 0502 ARMS 5.6
ファイル2:
ID Date Feature Value
01 0501 PRCP 170
01 0502 PRCP 120
02 0501 ARMS 5.6
02 0502 ARMS 5.6
理想的には、2つのファイルの2行に同じID、日付、および機能がありますが、値が異なる場合、出力は2つのファイルを次のように比較したいと思います。
ID Date Feature Value1 Value2
もちろん、この要件はやや高いかもしれません。それはまるで
ID1 Date1 Feature1 Value1 ID2 Date2 Feature2 Value2
また動作します。上記の例で出力したいと思います。
01 0501 PRCP 150 170
または
01 0501 PRCP 150 01 0501 PRCP 150
このように比較する方法とcsvファイルに出力する方法が最大の問題のようです。ありがとうございます。
Gillesの答えの出力例:commの出力は次のとおりです。
$ head -20 comm_output.txt ACW00011604,19490101,PRCP,0 AE000041196,20070402,TAVG,239 AE000041196,20070402,TAVG,244 AE000041196,20080817,TMIN,282 AE000041196,20130909,TAVG,350 AE000041196,20130909,TMAX,438 AE000041196,20130909,TMIN,294 AE000041196,20130910,TAVG,339 AE000041196,20130910,TAVG,341 AE000041196,20150910,TAVG,344
awkの出力は次のようになります。
$ head awk_output.csv , ACW00011604,19490101,PRCP,0,,, AE000041196,20070402,TAVG,239,,, AE000041196,20070402,TAVG,244,,, AE000041196,20080817,TMIN,282,,, AE000041196,20130909,TAVG,350,,, AE000041196,20130909,TMAX,438,,, AE000041196,20130909,TMIN,294,,, AE000041196,20130910,TAVG,339,,, AE000041196,20130910,TAVG,341,,, AE000041196,20150910,TAVG,344,,,
主張する場合、サンプル入力は次のようになります。
head file1.csv
ACW00011604,19490101,PRCP,0 ACW00011604,19490101,SNOW,0 ACW00011604,19490101,SNWD,0 ACW00011604,19490101,TMAX,289 ACW00011604,19490101,TMIN,217 ACW00011604,19490102,PRCP,30 ACW00011604,19490102,SNOW,0 ACW00011604,19490102,SNWD,0 ACW00011604,19490102,TMAX,289 ACW00011604,19490102,TMIN,228
head file2.csv
ACW00011604,19490101,SNOW,0 ACW00011604,19490101,SNWD,0 ACW00011604,19490101,TMAX,289 ACW00011604,19490101,TMIN,217 ACW00011604,19490102,PRCP,30 ACW00011604,19490102,SNOW,0 ACW00011604,19490102,SNWD,0 ACW00011604,19490102,TMAX,289 ACW00011604,19490102,TMIN,228 ACW00011604,19490102,WT16,1
答え1
2つのファイルを1行ずつ結合するツールを見てみましょう。
- 生地内容を気にせずに2つのファイルを1行ずつ結合します。
- コミュニケーションソートされたファイルをマージし、同じ行を記録します。これにより同じ行を消去できますが、異なる行を結合するには別のツールが必要です。
- 参加するソートされたファイルを結合して同じフィールドに一致させます。
- タイプ2つのファイルをマージできます。
- awkは、ユーザーが指定した規則に従って複数のファイルを結合できます。しかし、このような大きなファイルでは、汎用ツールではなく、最も適切なプロフェッショナルツールを使用すると、最高のパフォーマンスが得られます。
重複がないと仮定します。つまり、同じID、日付、および機能を持つ2つの行が1つのファイルに存在しません。重複項目がある場合、処理方法は処理方法によって異なります。また、ファイルがソートされていると仮定します。私もあなたの殻プロセスの交換、通常のshの代わりにbashまたはkshのようなもので、GNU coreutilsがあります(含まれていないLinuxおよびCygwinの場合)。
区切り文字が空白なのかタブなのかわかりません。空白があるとします。区切り文字が常に正確にタブの場合、タブを区切り記号(cut -d $'\t'
、、、)として宣言し、代わりに\ tを使用するとパフォーマンスがわずかに低下します。join -t $'\t'
sort -t $'\t'
[ \t]\+
LC_ALL=C
マルチバイト文字に関連するパフォーマンスの低下を防ぐには、ロケールを通常のASCII()に設定します。
行は1つのフィールドに基づいてのみ結合できるため、フィールドjoin
1〜3を単一のフィールドにまとめる必要があります。これを行うには、区切り文字を1と2の間、2と3の間、3と4の間に変更します。スペースを置き換えるために1-3を変更します;
。これにより、同じかどうかに関係なく、すべての行の組み合わせを取得できます。その後、sedを使用して同じ値を持つ行を削除できます。
join -a 1 -a 2 <(sed 's/[ \t]\+/;/; s/[ \t]\+/;/' file1.csv) <(sed 's/[ \t]\+/;/; s/[ \t]\+/;/' file2.csv) |
sed '/[ \t]\(.*\)[ \t]\+\1$/d' |
tr ';' '\t'
ペアリングできない行は4列の行で終わり、その行がファイル1にあるかファイル2にあるかは表示されません。ペアリングできないすべての回線を抑制するには、削除してください-a 1 -a 2
。
ほとんど同じ行がある場合、それをリンクして消去するのに時間がかかります。別の方法は、をcomm -3
使用して同じ行を消去することです。これにより、行は順番に並べ替えられますが、ファイル2の行には前のタブを持つ出力ストリームが生成されます。その後、awkを使用して、同じフィールド1〜3を持つ2つのファイルの連続した行をマージできます。これにはawkが含まれているため、他の行が多いと遅くなる可能性があります。
comm -3 file1.csv file2.csv |
awk '
$1 "\t" $2 "\t" $3 == k { if ($4 != v) print k "\t" v "\t" $4; next; }
{ print k "\t" v }
{ k=$1 "\t" $2 "\t" $3; v=$4; }
'
答え2
100万行を含む2つのファイルをすばやく比較する方法を見つけました。私の必要性は、2つのファイルが同じでなければならないということです。 diffコマンドは遅いですが、より高速にするには、ファイルを比較する前にソートするだけです。
だから基本的に:
sort file01.txt > file01_sorted.txt
sort file02.txt > file02_sorted.txt
次にdiffコマンドを実行します。
diff file01_sorted.txt file02_sorted.txt
または、ソートされたファイルに対してmd5sumを実行できます。
md5sum file01_sorted.txt
md5sum file02_sorted.txt
答え3
編集:この回答はあなたの周りの誰にでも適しているかもしれません。システムに200GBのRAMを使用できます。。こんな。
diff --side-by-side --suppress-common-lines file1.csv file2.csv
既定値は で、|
130 文字の広行区切り記号 (必要に応じて改行を含む) です。入力形式と同じではないようです。
次のことを試してみてください。
diff --old-line-format="%l$(printf '\t')" --new-line-format="%L" --unchanged-line-format="" file1.csv file2.csv