ファイルの1行をポップ(読み取りおよび削除)する方法は?

ファイルの1行をポップ(読み取りおよび削除)する方法は?

ファイルの最後の行を取得して削除しようとします。

次の行を読んでください。

sed -n '$p' file
# or
tail -n 1 file

次の行を削除してください。

sed -i '$d' file

これがうまくいきましたが、これを行う方法はありますか?単一コマンド

答え1

一般のコメントが何であれ、ファイルの最後の行を切り取るには、毎回ファイル全体を読む必要があります。無音、単一のプロセス/コマンドで実行されるか、2〜3つのプロセス/コマンドで実行されるか。

sed -iとは異なり、tailファイルの最後の行を決定するために最初からファイルを読み取らないほどスマートです。また、Linuxには、O(1)時間以内に大きなファイルの終わりを「ポップ」できるtruncate(1)ユーティリティがあります。tail

# usage popline file [line_count, 1 by default]
popline()(LC_CTYPE=C; l=`tail -n "${2:-1}" "$1"; echo t`; l=${l%t}; truncate -s "-${#l}" "$1"; printf %s "$l")

$ wc -l /tmp/foo
3579500 /tmp/foo
$ cp /tmp/foo /tmp/foo1 && time sed -i '$d' /tmp/foo1

real    0m1.077s
user    0m0.457s
sys     0m0.156s
$ cp /tmp/foo /tmp/foo1 && time popline /tmp/foo1
 */

real    0m0.052s
user    0m0.002s
sys     0m0.003s

答え2

目的は、1つのコマンドを使用してファイルの最後の行を出力し、同時に元のファイルからその行を削除することです。

sed -i -e '${w /dev/stdout' -e 'd;}' file

これにより、次のsedスクリプトが実行されます。

${
    w /dev/stdout
    d
}

最後の行を書き、/dev/stdout削除します。他のすべての行は、このオプションを使用して元のファイルに書き戻されます-i

コマンドの出力ファイル名を区別する他の方法がないためw(リテラル改行文字を挿入することに加えて)、コマンドラインのスクリプトは2つの部分に分割する必要があります。

そしてed

ed -s file <<END_ED
p
d
w
END_ED

edファイルを開き、fileファイルの最後の行にカーソルを置きます。最初のコマンドは行を標準出力として印刷し、2番目のコマンドはそれを削除し、最後のコマンドはバッファをファイルに書き換えます。大容量ファイルにはお勧めできませんed

関連情報