数字のみを含む非常に大きなファイルがあります。ドキュメント -
123212
234234
12324
1243223
5453443
各行を他のすべての行とペアリングしたいと思います。出力は次のとおりです
123212,234234
123212,12324
123212,1243223
123212,5453443
234234,123212
234234,12324
234234,1243223
234234,5453443
12324,123212
12324,234234
12324,1243223
12324,5453443
1243223,123212
1243223,234234
1243223,12324
1243223,5453443
5453443,123212
5453443,234234
5453443,12324
5453443,1243223
これは、入力ファイルに50L以上のレコードが含まれているためです。したがって、ループを介してこれを行うと、高価な作業になります。
答え1
この出力を生成するすべての方法は高価です。ただし、このアプローチはファイルがRAMよりはるかに大きい場合でも機能します。
$ while read n; do awk -v n="$n" '$1!=n{print n "," $1}' file; done <file
123212,234234
123212,12324
123212,1243223
123212,5453443
234234,123212
234234,12324
234234,1243223
234234,5453443
12324,123212
12324,234234
12324,1243223
12324,5453443
1243223,123212
1243223,234234
1243223,12324
1243223,5453443
5453443,123212
5453443,234234
5453443,12324
5453443,1243223
複数行に書き込む
while read n
do
awk -v n="$n" '$1!=n{print n "," $1}' file
done <file
read n
file
一度に1つの数字を読んでください。それぞれに対して awk スクリプトを実行して、最初の列に出力セクションを作成しますn
。n
このオプションは、シェル変数と同じ値で名前付き-v n="$n"
awk変数を生成します。この条件は、ファイル内のこの行と番号の異なる行を選択します。この行の場合は、番号、カンマ、行番号を順番に印刷します。n
n
$1!=n
file
n
n
答え2
私はジョンのコメントに同意します。何があっても費用がかかります。
join -o 1.2,1.3,2.2,2.3 -j 1 <(awk '{printf "%s %d %s\n", "x", FNR, $0}' file) \
<(awk '{printf "%s %d %s\n", "x", FNR, $0}' file) |
awk '$1 != $3{print $2, $4}'
それぞれを使用して2つのプロセス代替インスタンスを起動しawk
、ファイルの内容を返し、各レコードの先頭に2つの合成フィールドを挿入できます。最初のフィールドには固定値(x
上記の例では)が含まれ、2番目のフィールドには行番号が含まれています。その後、これはjoin
結合フィールドとして指定されたフィールド1に供給できます。これにより、プロセスは、2番目のインスタンスのすべてのレコードと一致する最初のインスタンスのすべてのレコードを置き換えます。後処理装置を使用して、awk
独自に一致するレコードインスタンスを削除します(この場合、行番号が同じであるという事実を利用します)。
答え3
まったく異なるアプリケーションの使用を考えてみますか?KDB+?
(32ビット版は無料です -ビールのようにメモリ制限は4GBです)
いくつかの基本事項:
ファイルを単一の列数値のリストとしてロードします。
flip (enlist "I";",") 0: hsym `$"/path/to/input"
アプリケーション
cross
機能。a cross a:... <from above>
q
(kdb +の言語)は非常に簡潔であるかもしれませんが、変数の割り当て(たとえば、にa:42
設定)を順番に割り当てて使用できることを意味します。ここでは、直接実行できるようにファイル入力を変数に割り当てます。42
a
a
cross
文字列出力を準備します。
"," 0: flip a... <from above>
0:
結果をカンマ区切り文字列として準備するために再利用されます。
出力ファイルに書き込みます。
(hsym `$"/path/to/output") 0: ","... <from above>
- 今回は、関数の使い方を明確にするために
()
左側のパラメータを囲む必要があります。最後にここに0:
hsym
0:
第三ファイルが作成された時間。
- 今回は、関数の使い方を明確にするために
一緒に入れてください:
(hsym`$"/path/to/output")0:","0:flip a cross a:flip(enlist"I";",")0:hsym`$"/path/to/input"
今悪いニュースがあります…
32ビットフリーバージョンの4GB RAM制限は、約32ビットしか処理できません。6000ジュール...
q)\ts (hsym`$"output6k.txt")0:","0:flip a cross a:flip(enlist"I";",")0:hsym`$"test6k.txt"
23428 3378126736
q)count distinct flip (enlist "I";",") 0:hsym`$"test6k.txt"
6000
\ts
ディスプレイは24秒もかからず、ほぼ3.4GBのメモリを占有します。
(とにかく私の努力を無駄にしないために、これを答えとして投稿することにしました...)
答え4
各行を互いに結合するSQLiteデータベースを作成します。
sqlite3 tmp.db
sqlite> CREATE TABLE T (x INTEGER);
sqlite> .import input_file T
sqlite> .mode csv
sqlite> .output output_file
sqlite> SELECT * FROM T JOIN T AS S WHERE T.x != S.x;
このソリューションは入力ラインの順序を保証しませんが、プロセスを開始するだけで外部ループがなく、限られたRAMで動作する必要があります。
修正する:
値を独自に関連付けないように select 文を変更します。同じ行にない限り、同じ値が正しい場合は使用してくださいWHERE T.rowid != S.rowid
。