処理しなければならない大きなファイルがありますが、機能しないようないくつかのスクリプトを作成した後、ファイルの行の一部が実際にはタブで区切られず、スペースで区切られていることがわかりました。
質問:空白で区切られた行をタブで区切られた行に変更する最善の方法は何ですか?
ファイルには1行に4つのエントリが含まれており、合計5000のエントリがあり、そのうち約150はタブで区切られず、スペースで区切られています。
答え1
tr ' ' '\t' < file 1<> file
各空白文字はタブ文字に置き換えられます。
人々が安全ではないと言うことに応じて:
シェルは、ファイル記述子 0 で読み取り用にファイルを開き、読み取りおよび書き込み用にファイル記述子 1 でファイルを開きます。これらのいずれかが失敗すると、実行されずに終了しますtr
。リダイレクトが成功するとtr
実行されます。
tr
ファイルを一度に1ブロックずつ読み、音訳した後、変更されていないブロックの代わりに修正されたブロックを出力します。
これを行うときは、通常ディスクにスペースを割り当てる必要はありません。例外は、ファイルが最初からまれな場合、またはファイルシステムが書き込み中のコピーを実装する場合です。したがって、「利用可能なスペースなし」エラーが発生する可能性は少なくなります。
I / Oエラーなどの他のエラーは、プライマリディスクに障害が発生した場合、またはファイルシステムがシンプロビジョニングされたブロックデバイス(LVMスナップショットなど)にある場合に発生する可能性があります。どちらの場合もまれであり、いかなる場合でもテープに関連する可能性があります。 。バックアップに戻るには
それにもかかわらず、write()
システムコールが失敗した場合は、エラーを報告してtr
終了する必要があります。 stdoutが読み書きモードで開かれるので、いいえ切りました。ファイルを切り捨てるには、終了時に標準出力を明示的に呼び出すtr
必要がありますが、truncate()
これは意味がありません。
しかし、何が起こるのかは、ファイルが部分的に翻訳されていることです(tr
失敗するまで)。
しかし、tr
現在Debian sid amd64で見つかったGNUでは抜け穴write()
システムコールが失敗するとセグフォルトが発生し、標準出力(編集する、今libc6 Debianパッケージバージョン2.19-1以降が修正されました)。これは実際にファイルを破損します(ただし、切り捨てることはありません)。
tr ' ' '\t' < file > newfile && mv newfile file
file
正しく生成されないと置き換えられませんが、newfile
これに関連するいくつかの問題があります。
- すでに存在するものを傷つけないようにする必要があります
newfile
(シンボリックリンクも考慮)。 - 現在のディレクトリに対する書き込み権限が必要です。
- このファイルの追加コピーを保存するには、追加の記憶領域が必要です。
- 元のファイルの権限、所有権、作成時間、拡張属性などが失われます。
- ソースファイルがシンボリックリンクの場合は、通常のファイルに置き換えます。
tr ' ' '\t' < file 1<> file
perl -pi -e 's/ /\t/g'
障害が発生した場合perl
(ディスクがいっぱい)、元のファイルが失われ、perl
これまで正常に出力されたファイルのみが再インポートされるため、通常のファイルよりも安全です。
答え2
sed
を使用することもできます。
sed -i.bak 's/ /\t/g' filename
filename.bak
ファイルを編集する前にファイルが作成されます。
s/ /\t/g
=> これは、sed
ファイルのすべての行でスペースをタブに完全に置き換えるように指示します。
答え3
ファイルのすべてのスペースをタブに変更するには、を使用しますtr
。
tr ' ' '\t' <input_file >output_file
1つ以上のスペースの各順序を単一のタブに変更するには、を使用しますsed
。
sed -e 's/ */\t/g' <input_file >output_file
いくつかの sed 実装は\t
タブを理解し、他の実装はリテラルタブを期待します。
並べ替えられた列を含むファイルがあり、可変数のスペースを使用して列を並べ替える場合は、タブで区切られた列を持つように変換できます。unexpand
。