bashスクリプトを使用して、巨大なテキストファイルから最初の行を繰り返し削除する必要があります。
現在使用していますsed -i -e "1d" $FILE
-削除には1分程度かかります。
これを達成するためのより効率的な方法はありますか?
bashスクリプトを使用して、巨大なテキストファイルから最初の行を繰り返し削除する必要があります。
現在使用していますsed -i -e "1d" $FILE
-削除には1分程度かかります。
これを達成するためのより効率的な方法はありますか?
回答:
尾を試してください:
tail -n +2 "$FILE"
-n x
:最後のx
行を印刷します。tail -n 5
入力の最後の5行が表示されます。+
一種の符号は引数を逆にしtail
、最初のx-1
行以外のものを出力させます。tail -n +1
ファイル全体tail -n +2
、最初の行以外すべてを印刷します。
GNUはよりtail
もはるかに高速ですsed
。tail
BSDでも利用可能で、-n +2
フラグは両方のツールで一貫しています。詳細については、FreeBSDまたはOS Xのマニュアルページを確認してください。
sed
ただし、BSDのバージョンは、よりも遅くなる可能性があります。彼らはどうやってそれを管理したのだろう。スクリプトを解釈したり、正規表現を適用したりするなど、かなり複雑な操作を行いtail
ながら、ファイルを1行ずつ読み取る必要がありますsed
。
注:使いたくなるかもしれません
# THIS WILL GIVE YOU AN EMPTY FILE!
tail -n +2 "$FILE" > "$FILE"
しかし、これはあなたに空のファイルを与えるでしょう。その理由は、リダイレクト(>
)がtail
シェルによって呼び出される前に発生するためです。
$FILE
tail
tail
プロセスのstdoutをにリダイレクトします$FILE
tail
今は空から読む $FILE
ファイル内の最初の行を削除する場合は、次を使用する必要があります。
tail -n +2 "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE"
&&
問題がある場合、ファイルが上書きされないことを確認します。
-r
オプションでBSD 'tail'を使用する場合、通常のバッファはデフォルトで32kになります。システムのどこかにバッファ設定があるのでしょうか?または-n
、32ビットの符号付き番号ですか?
tail
、どのファイルサイズでも機能します。
-n N means output the last N lines, instead of the last 10; or use +N to output lines starting with the Nth
-iを使用すると、「>」演算子を使用せずにファイルを更新できます。次のコマンドは、ファイルから最初の行を削除し、ファイルに保存します。
sed -i '1d' filename
unterminated transform source string
sed -i '1,2d' filename
tail -n +2
。なぜそれがトップアンサーではないのか分かりません。
いいえ、それはあなたが得ようとしているのと同じくらい効率的です。あなたは少し速く(起動時間と処理引数が少ない)仕事をすることができるCプログラムを書くことができますが、おそらくファイルが大きくなるにつれてsedと同じ速度になる傾向があります(そして、私はそれが1分かかる場合は大きいと思います) )。
しかし、あなたの質問は、それが解決策を前提としているという点で、他の多くの問題と同じ問題に悩まされています。方法ではなく、何をしようとしているのかを詳しく教えていただければ、より適切なオプションを提案できる可能性があります。
たとえば、これが他のプログラムBが処理するファイルAである場合、1つの解決策は、最初の行を削除せずに、プログラムBを変更して別の方法で処理することです。
すべてのプログラムがこのファイルAに追加し、プログラムBが現在、最初の行を読み取って処理してから削除するとします。
プログラムBを再設計して、最初の行を削除しようとせずに、ファイルAへの永続的な(おそらくファイルベースの)オフセットを維持して、次に実行したときに、そのオフセットにシークすることができるようにします。そこの行、そしてオフセットを更新します。
次に、静かな時間(真夜中?)に、ファイルAの特別な処理を行って、現在処理されているすべての行を削除し、オフセットを0に戻します。
プログラムがファイルを開いて書き換えるよりも、ファイルを開いてシークする方が確かに高速です。この説明では、もちろんプログラムBを制御できることを前提としています。それが事実であるかどうかはわかりませんが、さらに情報を提供すると、他の解決策が考えられる場合があります。
awk FNR-1 *.csv
おそらくより高速です。
パックスが言ったように、あなたはおそらくこれより速くなることはないでしょう。その理由は、ファイルの先頭からの切り捨てをサポートするファイルシステムがほとんどないため、これは、ファイルのサイズがn
であるO()操作n
になるためです。はるかに速くできるのは、最初の行を同じバイト数で(おそらくスペースまたはコメントで)上書きすることです。これは、何をしようとしているのかによって異なります(ところで何ですか)。
sponge
utilのは、一時ファイルをジャグリングの必要性を回避します:
tail -n +2 "$FILE" | sponge "$FILE"
sponge
確かに、受け入れられているソリューションよりもはるかにクリーンで堅牢です(tail -n +2 "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE"
)
sponge
、ファイル全体をメモリにバッファリングしますか?数百GBの場合は機能しません。
sponge
を吸収します。
あなたの場所にファイルを変更したい場合は、常に元使えるed
代わりにのSを後継者をtreaming sed
:
ed "$FILE" <<<$'1d\nwq\n'
ed
でもフルスクリーン端末、はるかに少ないのグラフィックワークステーションがあった前のコマンドは、オリジナルのUNIXのテキストエディタでした。ex
エディタは、最高のタイピングが大腸プロンプトででたときに、使用しているものとして知られているvi
、ある元の傾向が見られたバージョンed
と同じコマンドの作業の多くは、。一方でed
対話的に使用されることを意味し、それはまた、このソリューションが何をしている、それにコマンド文字列を送信することにより、バッチモードで使用することができます。
シーケンスは、<<<$'1d\nwq\n'
ここでは、文字列(のためのBashのサポートを利用しています<<<
)とPOSIXの引用符($'
... '
)フィード入力にするed
:二行からなるコマンド1d
、Dの eletesがライン1に続いて、wq
これ、ワットに出儀式ファイルバックディスクとは、qは編集セッションをuits。
vimを使用してこれを行うことができます:
vim -u NONE +'1d' +'wq!' /tmp/test.txt
処理時にvimはファイル全体を読み取らないため、これはより高速になります。
+wq!
シェルがbashの場合は引用する必要があります。多分それ!
が単語の最初ではないからではないでしょう、しかし物事を引用する習慣を身につけることは多分周りに良いでしょう。(そして、不必要に引用しないことで超効率を追求するのであれば、1d
どちらも引用する必要はありません。)
削除を高速化できないように思えるので、次のようにファイルをバッチで処理するのが良い方法だと思います。
While file1 not empty
file2 = head -n1000 file1
process file2
sed -i -e "1000d" file1
end
これの欠点は、プログラムが途中で終了した場合(または、そこにいくつかの不良SQLがある場合-「プロセス」の部分が停止またはロックアップする原因)、スキップされるか、2回処理される行が存在することです。 。
(file1にはSQLコードの行が含まれています)
N-1行でテールを使用し、それをファイルに送り、その後古いファイルを削除し、新しいファイルの名前を古い名前に変更すると、うまくいきますか?
プログラムでこれを行っている場合は、各行を読み取った後、ファイルを読み取り、ファイルオフセットを覚えているので、その位置に戻って、1行少ないファイルを読み取ることができます。