私はちょうど大きな(ギガバイト)サイズのファイルからいくつかの行を切り取る必要がある問題に遭遇し、メモリからファイルを読み取ろうとするとCPU使用率が発生する可能性があることに気づき、その場で編集したいと思いました... ...次の問題が発生しました。
...そしてこれらは:
ext3
しかし、私は他のことについて考えています。私は、すべてのファイルシステム(たとえば)がディスク領域にマップされたファイルの断片のようなものを記述できるように、リンクリストのようなものを使用する必要があると思います(ただしわかりません)。 。
したがって、次のことを行うことが可能でなければなりません。たとえば、次のようなファイルがあるとしますbigfile.dat
(数字はバイトオフセットを表す必要がありますが、ソートするのは少し難しいです)。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
L 1\n L 2\n L 3\n L 4\n L 5\n L 6\n
原則として、検索用にファイルをターミナルアプリケーションにロードできます。ツールを呼び出すと仮定し、同じファイル(行番号を含む)がどのように表示されるかとeditsegments bigfile.dat
似ているとします。less -N bigfile.dat
1 1 L 1
2 2 L 2 *
3 3 L 3
4 4 L 4 *
5 5 L 5
6 6 L 6
bigfile.dat (END)
コマンド(たとえば、行の削除)を入力してd
別のキーまたはマウスをクリックすると、*
行2と4の間のすべての項目を削除する必要があるというメッセージが表示されたとします。その後、プログラムは応答し、次のことを表示します。
1 1 L 1
2 5 L 5
3 6 L 6
bigfile.dat (END)
一番左の最初の列には「新しい」行番号(切り取り前)が表示され、2番目の列には「前」行番号(切り捨て前)が表示され、次に実際の行の内容が表示されます。
さて、この偽のアプリケーションが終了した後に何が起こるのか想像してください。editsegments
何よりもbigfile.dat
影響を受けません。ただし、同じディレクトリにbigfile.dat.segments
次の内容を含む追加のテキストファイルがあります。
d 4:15 # line 2-4
bigfile.dat.iedit
...また、"symlink"のような特別なファイルが表示されます。これを「it」と呼びます。
bigfile.dat.iedit
基本的に、これらすべての結果は次のように今開こうとすると次のようになりますless -N bigfile.dat.iedit
。 「編集された」コンテンツをインポートしたいと思います。
1 L 1
2 L 5
3 L 6
bigfile.dat (END)
...これは、OSに何らかの方法で指示し、$FILE.iedit
開いたときに最初に開いて元のファイルのバイト4〜15を省略する必要が$FILE.segments
あるd 4:15
ことを示すようにすることで達成できます。これにより、次のような結果が得られます。次の結果:
0 1 2 3 4 5 6 7 8 9 10 11 12,3,4 15 16 17 18 19 20 21 22 23
L 1\n
L
2
\n
L
3
\n
L
4
\n
L 5\n
L 6\n
0 1 2 3---------------------------------- -->16 17 18 19 20 21 22 23
つまり、仮説ファイルシステムの概念では、コンテンツの各バイトにはチェーンの次のバイトへの「リンク」も含まれます。ファイルシステムにスクリプトに基づいて新しい接続リストを構築し、次のようにコンテンツを提供するように指示できる必要があります。変更された接続のリストとして表示される特別なファイル(シンボリックリンクまたはパイプ)。
これはタイトルで「スクリプト可能」という意味です。 「新しい」接続リストは、$FILE.segments
ユーザーがテキストエディタで編集できる(またはフロントエンドアプリケーションで生成できる)スクリプトファイル()によって制御できます。 「複数回」とは、bigfile.dat
プロセス中にまったく変更されないことを意味します。したがって、今日の最初の(元の)ギガバイトを編集し、進行状況を($FILE.segments
)に保存できます。その後、明日の2番目のギガバイトを編集し、進行状況を($FILE.segments
)に戻す - 元のコンテンツは変更されbigfile.dat
ていません。
editsegments --finalize bigfile.dat
すべての編集が完了したら、新しい接続リストをの内容に永続的にエンコードする一種のコマンド(たとえば)を呼び出すことができますbigfile.dat
(それに応じて、bigfile.dat.segments
およびを削除bigfile.dat.iedit
)。あるいは、より簡単には、次のようにすることができます。
cp bigfile.dat.iedit /path/to/somewhere/else/bigfile.modified.dat
もちろん、d
eleteスクリプトコマンドに加えてr
eplaceコマンドもあります。たとえば、次のようになります。
r 16:18 AAA
...説明:バイト16と18の間の内容を空白の後の18〜16 + 1 = 3バイトに置き換えます(例:)AAA
。リンクされたリストは、実際にはスクリプトコマンドの内容自体に「接続」することができます(図の下もエレテを含むd
)。
0 1 2 3 4 5 6 7 8 9 10 11 12,3,4 15 16 17 18 19 20 21 22 23
L 1\n
L
2
\n
L
3
\n
L
4
\n
L
5
\n
L 6\n
0 1 2 3---------------------------------- -->| 19 20 21 22 23
.
.
.
.
.
.
.
\n
r
1
6
:
1
8
AAA
\n
.
.
.
.
今、私はプログラムがhexedit
(上記のように)次のようになりたいと思います。ここ)はファイルをその場で変更します。しかし、私はスクリプト可能性の利点(ターミナルアプリケーションでもGUIアプリケーションで管理できれば良いでしょう)と実際に元のファイルがないという利点があります。変更、すべての編集内容が準拠していることが確認されるまで。
そんなことができるのかよく分からない。下痢可能であっても(単純なユーザープログラムではなく)専用ドライバーが必要かもしれないと思いますが、とにかく尋ねる価値があると思います。 Linuxには似たようなものがありますか?
答えてくれてありがとう。
応援します!
答え1
ディスクのファイル構造は、使用するファイルシステムによって異なります。実際のファイルシステムでは、あなたが説明するような接続リストを使用しません(fseek(3)
耐え難いことです)。これに最も近いのはマイクロソフトのものです。脂肪、デフォルトでは、データブロックのポインタを配列に移動して非表示にします。
ただし、ほとんどのファイルシステムはファイル内のデータブロックへのいくつかのポインタベースの参照を使用するため、原則としてファイル全体の内容ではなく、少数のポインタを混在させ、ブロックを表示してファイルを切り取ることができます。ブロック内のファイル。ファイルの中央部分は無料です。残念ながら、これは非常に便利な作業ではありません。ファイルブロックはかなり大きく(通常は4KiB)、ファイルの構造(ラインまたは他のサブセグメンテーション)と合理的に整列することはほとんどありません。
答え2
あなたが描いたものは非常に似ているようです。やり直すテキストエディタやり直しリスト変更されていないソースファイルの場合やり直しリストgvim
私は一つがあると確信しています。持続性元に戻す/やり直しリスト、それを活用(?)することができ、emacs
そのようなリストが確実にあることを知っています。スクリプトを使用すると、必要に応じて実行するように同軸できますelisp
。セッション間のEmacsのUNDO履歴の保存。
ところで、このような大きなファイルがある場合は、次のような不要な作業をすべてオフにすることをお勧めします。自動保存、構文強調(ゆっくり大きいemacsファイル)など、32ビットシステムのemacsは256MBです。ファイルサイズ制限。
提案したのと同じくらい簡潔ではありませんが、多くの変更がなければ便利です。
答え3
通常、ファイル全体をメモリに入れないと、ファイルを内部で編集することはできません。私はあなたが本当にしたいことは、特定の行がない古いファイルのコピーである新しいファイルを持つことを前提としています。これはUnixユーティリティを使用してhead
簡単に実行できますtail
。たとえば、ファイルから行5、12、および52を除くすべての内容をコピーするには、次のようにします。
head -n 4 bigfile.dat > tempfile.dat
tail -n +6 bigfile.dat | head -n 6 >> tempfile.dat
tail -n +13 bigfile.dat | head -n 39 >> tempfile.dat
tail -n 53 bigfile.dat >> tempfile.dat
これらのユーティリティについてよくわからない場合は、さらに詳しく説明します。
このhead
ユーティリティはファイルの最初のn行を印刷します。位置引数が指定されていない場合は、標準入力をファイルとして使用します。この-n
フラグは、印刷する行数をヘッドに通知します。したがって、head -n 2
標準入力の最初の2行だけが印刷されます。
このtail
ユーティリティはファイルの最後のn行を印刷します。 headと同様に、ファイルまたは標準入力から読み取ることができます。 -nフラグは、tailの終わりから印刷する行数を示します。数字の前にプラス記号を追加して、tail が最初から多くの行をファイルの最後から印刷するようにすることもできます。たとえば、tail -n 2
標準入力の最後の2行を印刷します。ただし、tail -n +2
2行目から始まるすべての行が印刷されます(1行目は省略されています)。
したがって、通常、ファイル内の[x、y)の範囲の行を印刷するには、次のようにします。
`tail -n +x | head -n d`
ここで d = y - x です。このコマンドは新しいファイルを生成します。必要に応じて古いファイルを削除できます。これの利点は、一度に1行だけメモリに保持する必要があるため、RAMが非常に早く埋められないことですhead
。tail
答え4
sed スクリプト操作のように聞こえます。 IIRCは、このタイプの作業用に設計されています。行ごとの処理、同じ命令セットの反復処理、正規表現はすべて1つのツールに結合されています。私はそれが仕事をすることを知っていますが、あなたの仕事を案内する以外にあなたを導くことはできません。マニュアルページ。