私の入力テキストファイルには1行のヘッダーが含まれており、その後に空白で区切られたxyとx、yの64ビット整数を含むソートされた行のリストがあります。入力ファイルの長さは数百万短くなります。
今私は欲しい2行目から#end#まで削除value <= $input で始まるすべての行。これにより、各ゲームの行全体が削除されます。これまでの私の優雅ではない解決策は次のとおりです。
head -1 inputFile > inputFile2 # ヘッダーを保持 lineNum=$( grep -n $input test | cut -f1 -d ':' ) # $input と一致する行を探す tail -n +$( $lineNum+1 ) inputFile >> inputFile2 # 値 > $input に達するまで下に入力をスキップします。 rm 入力ファイル mv入力ファイル2入力ファイル
入力ファイルの例
5066314878607:a1:a2:a3:a4:a5 1 27 3 27 7 27 11 27 13 27 17 27 ...
[GNUツールの分割] inputFileはinputFile-1とinputFile-2(2コア、可能であればzコア)に分けられます。
入力ファイル-1: 5066314878607:a1:a2:a3:a4:a5 1 27 7 27 13 27 入力ファイル-2 5066314878607:a1:a2:a3:a4:a5 3 27 11 27 17 27
これで inputFile-1 は ' まで処理され、完了します。727 '。基本的なinputFileには、次の2行だけを含めたいと思います。 (分割inputFile-1の<=に注意してください。ただし、ループ分割によって元のinputFileから削除された単純な<= xではありません。)
1 27 7 27
これにより、inputFileは次のようになります。
5066314878607:a1:a2:a3:a4:a5 3 27 11 27 13 27 17 27
現在Ubuntu 16.04で実行されていますが、これはすべての最新のLinuxディストリビューションでも同じです。
質問:
- 既存のコードを改善できますか?
- 個別に削除された多くのファイルを処理するように一般化するにはどうすればよいですか?
個別に処理された各inputFile-xは、順次処理されます。ループ分割によって、基本ファイルから処理された行を削除する方法がわかりません。 特に、異なる速度の多くのコンピュータで実行されるため、inputFile-1はライン300として処理でき、inputFile-2はライン500として処理できます。
それぞれ別々に処理されるzコアに一般化する方法について説明します。 inputFile は inputFile-1 inputFile-2 inputFile-3... inputFile-z にループ分割されます。 [つまり、50コアの場合、分割-nr/$z: 分割-nr/50 inputFile]
Core1:inputFile-1(ライン2から#end#までの値)<= $input1 -->リポジトリリスト/配列を削除1。これで、Remove1で一致する値のみが元のinputFileから削除されます。各コアで作業を続けます。
答え1
@SatoKatsuraは既にコメントで最初の質問に答えています。awk -v cutoff=299851915672 'FNR == 1 || $1+0 > cutoff+0' inputFile
2番目の質問で質問したものを説明するのは難しいですが(アルゴリズムや疑似コードで質問を更新できますか?)、プロセスの多く(50?)インスタンスを一度に実行したいと思われます(CPUコアごとに1回システム)。 )。それでは、ファイルを50個の小さなファイルに正しく分割し始めました。
パズルから欠けているのは、プロセスを並列に実行するにはGNU parallel
(またはオプションをxargs
使用)を使用する必要があるということです。-P
たとえば、
find . -type f -name 'inputFile-*' -print0 |
parallel -n 1 \
awk -v cutoff=299851915672 \
\'FNR == 1 \|\| \$1+0 > cutoff+0 {print \> FILENAME".out"}\'
(下記参照1、2、3参照)
parallel
デフォルトでは、システムではコアごとに1つのプロセスが実行されます。-j
同時ジョブ数を指定するオプションを使用して、それを上書きできます。
スクリプトawk
は、各入力ファイルの出力を.out
同じ名前と追加の拡張子を持つファイルに保存します(例:inputFile-1
->)inputFile-1.out
。もう 1 つの大きなファイルにマージするには、次のようにしますcat
。
cat inputFile*.out > complete.output.txt
rm -f *.out
注1:実行したいコマンドラインから引用符やその他の特殊文字(例:、、、、など)をエスケープするには、バックスラッシュを使用する必要があります|
。スクリプトを別のファイル(最初の行として使用)に保存し、を使用して実行可能にし、スクリプトを並列に実行する方が簡単です。$
>
&
;
parallel
awk
#!/usr/bin/awk -f
chmod
注2:あなたが実際に何を求めているのかわからないので、これはまさにあなたが要求するものを実行できないかもしれません。複数のファイルを並列に処理する方法の一般的な例です。awk
(理解できない)要件を満たすには、スクリプトをほぼ確実に変更する必要があります。
注3:複数のプロセスを並列に実行して節約した時間は、入力を複数のファイルに分割するのに必要な時間と、各ファイルに対してawk
新しいプロセスインスタンス(スクリプトなど)を起動するオーバーヘッドよりはるかに大きいことがわかります。文書。これは、ファイルの性質とサイズ、および各ファイルに対して実行される処理の性質によって異なります。並行して実行しても、常に結果をより早く得るという意味ではありません。または、実行中の作業が複雑すぎて理解しにくく、他のデータと複製するのが難しい場合があります。
答え2
完全なファイルを読むことはできませんか?例:ソートされているので、バイナリ検索を実行して関連行のバイトを見つけることができます。 ソートされたテキストファイルのバイナリ検索そしてhttps://gitlab.com/ole.tange/tangetools/blob/master/bsearch/bsearch
ほとんどの行処理を避けることはできますか?はい、関連する行を見つけたら、残りの部分をコピーできます。
このバイトを使用すると、1行のヘッダーでhead
操作を実行し、tail
見つかったバイトで操作を実行できます。