ファイルの最後の行を取得して削除しようとします。
次の行を読んでください。
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
。