尾の反対:最後のn行を除くすべての行


36

UNIXコマンドラインフィルターでファイルの最後のn行を破棄するにはどうすればよいですか?

それは逆の並べ替えになりますtailtail最初のn行を破棄し、残りをパイプ処理しますが、コマンドを除いてすべてをパイプ処理したいです、最後のn行。

残念ながら、私はそのようなものを見つけていません- head助けにもなりません。編集:少なくともSolarisでは負の引数を取りません。

更新:私は主に大きなファイル、つまりログファイルで動作するソリューションに興味があります。ここでは、最後の数分間で何が起こったのかを調べることができます。


FYIヘッドを使用した場合:配置することにより、「 - 」以下に示すように-nオプションを指定した番号の前に、それは、すべての各ファイルの行ではなく、最後のN行を出力
G声

回答:


38

GNUをお持ちの場合はhead、使用できます

head -n -5 file.txt

の最後の5行を除くすべてを印刷しますfile.txt

head -n負の引数をとらない場合、試してください

head -n $(( $(wc -l file.txt | awk '{print $1}') - 5 )) file.txt

11
(そしてfile.txt、少なくとも6行の長さで祈る...)
CVn

1
悲しいことに、この非GNUバージョンはストリームでも動作しません。
Armand

1
@MichaelKjörling少なくともubuntuでは、それは問題ではありません。ファイルの行がで指定された行より少ない場合、headエラーなしで空の出力が返されます。
-Alphaaa

私が間違っていなければ、head -n 5は最初の5行を印刷します。最後の5行だけではありません
...-pypmannetjies

8
head file.txt               # first 10 lines
tail file.txt               # last 10 lines
head -n 20 file.txt         # first 20 lines
tail -n 20 file.txt         # last 20 lines
head -20 file.txt           # first 20 lines
tail -20 file.txt           # last 20 lines
head -n -5 file.txt         # all lines except the 5 last
tail -n +5 file.txt         # all lines except the 4 first, starts at line 5

1
受け入れられた答えで答えられなかったこれは何を追加しますか?また、他の回答と同様に、回答を数行説明することで大幅に改善されます。
music2myear

1
非常に良い要約
ruanhao

5

最後の行を削除する簡単な方法を次に示します。これはBSDなどで機能します。

sed '$d' input.txt

式は「最後の行で削除します」と表示されます。それがsedデフォルトの動作であるため、他の行が印刷されます。

それらを連結して複数の行を削除できます

sed '$d' input.txt | sed '$d' | sed '$d'

確かに少し手間がかかりますが、ファイルをスキャンするのは1回だけです。

他の回答については、こちらをご覧ください。 https //stackoverflow.com/questions/13380607/how-to-use-sed-to-remove-last-n-lines-of-a-file

ここに私のお気に入りの1つから適応されたワンライナーがあります:

N=10
sed -n -e ':a' -e "1,$N!{P;N;D;};N;ba"

私はそれを解読するのが楽しかったし、あなたもそうすることを望んでいる(:Nスキャンするときにバッファ行を実行するが、そうでなければかなり効率的だ。


3

私はあなたheadがなぜ選択肢ではないと思うのか興味があります:

~$ man head
...
-n, --lines=[-]K
        print the first K lines instead of the first 10; 
        with the leading `-', print all but the last K lines of each file

これは、たとえば次を使用して、目的に合っているようです。

head -n -20 yourfile.txt

5
これはGNUにのみ適用されることに注意してくださいhead。BSDにheadはこのオプションがないため、この答えは、GNU coreutils がない Solarisまたは他のUnix では機能しません。OPは、特にこれにUnixおよびUnix-Utilsのタグも付けました。
slhck

2
@slhck OPがこれがSolaris用であると述べたという事実は言うまでもありません。
CVn

残念ながら、誰かが私のSolarisに関する言及を削除しました。とにかく、headのバージョンはそれをサポートしていないと言っておかなければなりません。
ハンスピーターシュトルー

1
すみません Solarisに気づかず、またさまざまなバージョンのheadを認識していませんでした。
アンダースR. Bystrup

1
@hstoerr Solarisがタグに
追加されました

0

tail -n負の引数をとらない場合の別の方法は

tac file.txt | tail -n +6 | tac

これにより、最後の5行が削除されます


ありがとう!これは、これまで誰も思いつかなかった気の利いたアイデアです。残念ながら、この質問で私が念頭に置いていたユースケースにとっては非常に非効率的です:それが大きなファイルである場合、他のソリューションと同様に、1回以上完全に読まれるだけでなく、おそらくディスクがメモリに収まらない場合、tacによって一時ファイルに保存されます。
ハンス-ピーターステアー

@ハンス-ピーター非常に真実。python3スクリプトを書くことにしました。このgithub.com/atw31337/donkeyを試してください。出力オプションの使用をお勧めします。リダイレクトを使用するよりもはるかに高速に実行されます。
atw31337

うまく書かれています!ただし、ファイルを2回読み取ります。最後のn行をバッファリングする場合、これは実際には必要ありません。これは大きなファイルで問題になります。個人的にはもう必要ありませんが、それを改善する楽しみがあり、他の人がそれを必要とする場合は...結局のところ、質問にはいいねやブックマークがいくつかありました。
Hans-PeterStörr

@ハンスピーター。バッファサイズは、削除する行数に依存します。これは、ファイルから非常に多くの行を削除する必要がある場合に問題になる可能性があります。メモリ関連の問題を回避するために、スクリプトを書き直して、n値が高い行カウント方式とn値が低いバッファリング方式を使用しています。ただし、非常に大きなファイルでテストした後でも、元の行カウント方法の方が高速です。バッファ管理のオーバーヘッドが行数のオーバーヘッドを上回っているようです...または、何かが足りません。
atw31337

いいですが、BSDバリアントのMac OS Xの場合、デフォルトではtacコマンドはありません。:(敗北この種のユースケース。
ingyhere
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.