sedを使用してファイルの最後のn行を削除する方法


148

ファイルの末尾からn行削除します。これはsedを使用して実行できますか?

たとえば、2から4までの行を削除するには、次のように使用できます

$ sed '2,4d' file

しかし、行番号はわかりません。を使用して最後の行を削除できます

$sed $d file

しかし、私は最後からn行を削除する方法を知りたいです。sedまたはその他の方法を使用してそれを行う方法を教えてください。


2
@arashkordi:ファイルの下部ではなく、上部からの行数を使用します。
ams

スーパーユーザーに関する関連質問。
トール

//、たぶん、質問を言い換えるだけで 、それをより一般的なものにすることを検討しsedますか?
Nathan Basanese

1
sed $d fileエラーを返します。代わりに、$ Dは次のように、引用符で囲む必要があります:sed '$d' file
Akronix

回答:


221

についてはわかりませんsedが、次の方法で実行できますhead

head -n -2 myfile.txt

19
単純化のために+1。同等のsedコマンドは、お尻醜いです:sed -e :a -e '$d;N;2,5ba' -e 'P;D' file,5最後の5行のため)。
マークB

62
これはの一部のバージョンで機能しますがhead、標準ではありません。確かに、のための標準的なhead状態:The application shall ensure that the number option-argument is a positive decimal integer.
ウィリアムPursell

21
@WilliamPursellの回答に追加するには... Mac OSのデフォルトシェルでは、これは機能しません。
JDS 2015年

7
BSDではありませんが、質問はLinuxとタグ付けされています。
ams

3
マイナス1、OSXに加えて、これはUbuntu14に私のために働いていない、ので-head: illegal line count -- -2
マイケル・デュラント

30

nのハードコーディングがオプションである場合、sedへの順次呼び出しを使用できます。たとえば、最後の3行を削除するには、最後の1行を3回削除します。

sed '$d' file | sed '$d' | sed '$d'

2
これに加えて、ファイルをstdoutにダンプするのではなく、所定の場所でファイルを編集する-iが私にとってはうまくいきました。
WAF 2015年

27

sedのワンライナー

# delete the last 10 lines of a file
sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # method 1
sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # method 2

あなたが求めているもののようです。


@Thorあなたは変更することで、ファイルから削除されている行数を変更することができます10'$d;N;2,10ba'
Alexejマグラ

1
@AlexejMagura:以前のバージョンの回答についてコメントしていました。
2016年

22

面白い&シンプルsedtac解決策:

n=4
tac file.txt | sed "1,$n{d}" | tac

注意

  • "シェル$nsedコマンド内の変数を評価するには、二重引用符が必要です。一重引用符では、補間は実行されません。
  • tacされてcat逆に、参照man 1 tac
  • {}sedが分離するようにしている$nd(そうでない場合は、補間非存在にシェル試し$nd変数)

7
FYIなしtacOSX上で
マイケル・デュラント

1
@MichaelDurrant port info coreutils|| brew info coreutils;

19

を使用sedしますがd、範囲を指定してコマンドを使用することを目的として、シェルに計算を任せます(最後の23行を削除するため)。

sed -i "$(($(wc -l < file)-22)),\$d" file

裏側から最後の3行を削除するには:

$(wc -l < file)

ファイルの行数を示します:たとえば2196

最後の23行を削除したいので、左側または範囲の場合:

$((2196-22))

Gives:2174 したがって、シェル解釈後の元のsedは次のとおりです。

sed -i '2174,$d' file

-iインプレース編集をやって、ファイルが今ある2173本のライン!

新しいファイルに保存する場合、コードは次のとおりです。

sed -i '2174,$d' file > outputfile

15

このためにを使用できます。

使用する

$ head --lines=-N file > new_file

ここで、Nはファイルから削除する行数です。

元のファイルの内容から最後のN行を引いたものがnew_fileになりました


8

完全を期すために、私のソリューションを追加したいと思います。私はこれを標準で行うことになりましたed

ed -s sometextfile <<< $'-2,$d\nwq'

これは、インプレース編集を使用して最後の2行を削除ます(ただし、/tmp!!で一時ファイルを使用します)


5

非常に大きなファイルを完全に切り捨てるには、truncateコマンドがあります。行についてはわかりませんが、tail+ wcは行をバイトに変換できます。

file=bigone.log
lines=3
truncate -s -$(tail -$lines $file | wc -c) $file

ファイルが同時に書き込まれた場合、明らかな競合状態があります。この場合、使用する方が良いかもしれませんhead-ファイルの先頭からバイトを数えるので(ディスクIOに注意)、常に行の境界で切り捨てます(ファイルがアクティブに書き込まれている場合は、予想よりも多くの行になる可能性があります)。

truncate -s $(head -n -$lines $file | wc -c) $file

ユーザー名の代わりにパスワードを入力してログインに失敗した場合に便利なワンライナー:

truncate -s $(head -n -5 /var/log/secure | wc -c) /var/log/secure

4

これはあなたのために働くかもしれません(GNU sed):

sed ':a;$!N;1,4ba;P;$d;D' file

いいね。末尾のアポストロフィ(')を逃しました。
トール

コメントが遅くなって申し訳ありませんが、私は試してみました(私のAIX / posixに対応しています)。最後の行を除いてすべて印刷できませんでした。コードを読んでも、最後の4行がどのように削除されるのか理解できません。明示的なループは最初の4行にあるため、posixバージョンではなくdDまたはPGNU sedの後で確実にループします。行はの後に出力されないDようで、アクション行の「終わり」に渡らずに新しいループの作業バッファーに保持されます。
NeronLeVelu 2015年

@NeronLeVeluプログラムは、4行のウィンドウをパターンスペースに読み込み、次の行を追加して、ファイルの最後に到達するまで最初の行を出力し、残りの行を削除します。
ポトン2015年

@potongはい、私はGNU sedでテストしD、反対の効果を行った後にposixがそれをアンロードする行間のバッファーを保持します。
NeronLeVelu 2015年

4

上記の回答のほとんどは、GNUコマンド/拡張機能を必要とするようです。

    $ head -n -2 myfile.txt
    -2: Badly formed number

少し移植性の高いソリューションの場合:

     perl -ne 'push(@fifo,$_);print shift(@fifo) if @fifo > 10;'

または

     perl -ne 'push(@buf,$_);END{print @buf[0 ... $#buf-10]}'

または

     awk '{buf[NR-1]=$0;}END{ for ( i=0; i < (NR-10); i++){ print buf[i];} }'

ここで、「10」は「n」です。


2

ここでの回答により、sedはこのアプリケーションに最適なツールではないことをすでに理解しているはずです。

ただし、sedを使用してこれを行う方法はあると思います。アイデアは、EOFを押すことなく読み取ることができるまでスペースを保持するためにN行を追加することです。EOFに達したら、ホールドスペースの内容を出力して終了します。

sed -e '$!{N;N;N;N;N;N;H;}' -e x

上記のsedコマンドは、最後の5行を省略します。


2

次のコマンドを試してください。

n = line number
tail -r file_name | sed '1,nd' | tail -r

これがどのように機能するか説明してください。FYI-シェル変数を初期化するために、周りにスペースを入れるべきではありません=
codeforester 2018

@codeforester最初の行は私が推測するコメントでした。彼はtail -r、他の人がtac行の順序を逆にしていた場所を使用し、最後のn行をn最初の行にします。
Nicolas Melay

2

これは3つのステップで実行できます。

a)編集するファイルの行数をカウントします。

 n=`cat myfile |wc -l`

b)その数から削除する行数を引きます。

 x=$((n-3))

c)その行番号($x)から最後まで削除するようにsedに指示します。

 sed "$x,\$d" myfile

悪い数学。3行を削除する必要がある場合は、3を減算して1を加算します。計算で、ファイルに10行ある場合、10-3 = 7でありsed、7行目から10行目、つまり3行目ではなく4行目を削除している場合
mathguy

1

wc -l <file>を使用して行の総数を取得できます

head -n <total lines - lines to remove> <file>


1

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

for i in $(seq 1 3); do sed -i '$d' file; done;


1
これは、大きなファイルには高すぎる方法です。ファイル全体をn回読み取り、再書き込みする必要があります。と同じくらい多くのフォークsed
codeforester 2018

これは最も効率的な解決策ではないかもしれませんが、最も簡単で理解しやすい方法です
Dharam

0

私はこの解決策を好みます。

head -$(gcalctool -s $(cat file | wc -l)-N) file

ここで、Nは削除する行数です。


0
sed -n ':pre
1,4 {N;b pre
    }
:cycle
$!{P;N;D;b cycle
  }' YourFile

posixバージョン


0

最後の4行を削除するには:

$ nl -b a file | sort -k1,1nr | sed '1, 4 d' | sort -k1,1n | sed 's/^ *[0-9]*\t//'   

頭に比べて少し重い(特にリソース)。少なくともtac file | sed '1,4d' | tac、並べ替えてから、プリソースコストの多くのリソースが削除されるためです。
NeronLeVelu 2015年

@NeronLeVeluあなたは正しいですが、tacコマンドがないシステムもあります(たとえば、FreeBSD?)
mstafreshi

0

私はこれを思いつきました、ここでnは削除したい行の数です:

count=`wc -l file`
lines=`expr "$count" - n`
head -n "$lines" file > temp.txt
mv temp.txt file
rm -f temp.txt

少し回り道ですが、わかりやすいと思います。

  1. メインファイルの行数を数えます
  2. カウントから削除する行の数を引きます
  3. 保持して一時ファイルに保存する行数を出力します
  4. メインファイルを一時ファイルに置き換えます
  5. 一時ファイルを削除する

0

ファイルの最後のN行を削除するには、同じ概念を使用できます。

$ sed '2,4d' file

Nが5の場合、tailコマンドと組み合わせてファイルを反転できます。

$ tail -r file | sed '1,5d' file | tail -r > file

この方法は、head -n -5 fileコマンドが実行されない場所でも実行されます(Macなど)。


-2

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

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

1
少し説明していただければ助かります。
Richard Wiseman
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.