web-dev-qa-db-ja.com

Bashのファイルから最後の行を削除する

次の行を含むファイルfoo.txtがあります。

a
b
c

foo.txtの内容が次のようになるような単純なコマンドが必要です。

a
b
280
Fragsworth

GNU sed を使う:

sed -i '$ d' foo.txt

-iオプションは3.95より前のGNU sedバージョンには存在しないので、あなたはそれを一時ファイルのフィルタとして使う必要があります:

cp foo.txt foo.txt.tmp
sed '$ d' foo.txt.tmp > foo.txt
rm -f foo.txt.tmp

もちろん、その場合はsedの代わりにhead -n -1を使うこともできます。

MacOS:

Mac OS X(10.7.4以降)では、上記のsed -iコマンドと同じです。

sed -i '' -e '$ d' foo.txt
347
thkala

これは、特に大きなファイルでは、はるかに高速で簡単な解決策です。

head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt

一番上の行を削除したい場合は、これを使用してください。

tail -n +2 foo.txt

これは2行目から始まる出力行を意味します。

ファイルの上または下から行を削除するためにsedを使用しないでください - ファイルが大きい場合は非常に遅くなります。

250
John

私はここですべての答えに問題がありました。なぜなら私はHUGEファイル(〜300Gb)を使って作業していて、どのソリューションも拡張できなかったためです。これが私の解決策です:

dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )

つまり、(bcを使用して、ファイルの長さからその最後の行の長さの長さを引いたもの)で終わらせたいファイルの長さを調べ、その位置をファイルの終わりに設定します。 1バイトの/dev/nullddingします。

tailは最後から読み込みを開始し、ddはファイルの各行をコピー(および解析)するのではなく、ファイルを上書きするため、これは高速です。それが他の解決策がすることです。

注:これにより、ファイルから行が削除されます。自分のファイルで試してみる前に、ダミーファイルのバックアップまたはテストを行ってください!

103
Yossi Farjoun

ファイル全体を読んだり何かを書き換えたりせずにファイルから最後の行を削除するには、次のようにします。

tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}

最後の行を削除してそれを標準出力に( "ポップ")出力するには、そのコマンドをteeと組み合わせることができます。

tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})

これらのコマンドは非常に大きなファイルを効率的に処理できます。これはYossiの答えに似ていて、それに触発されていますが、それはいくつかの余分な関数を使うことを避けます。

これらを繰り返し使用し、エラー処理やその他の機能が必要な場合は、ここでpoptailコマンドを使用できます。 https://github.com/donm/evenmoreutils

52
ohspite

Macユーザー

ファイル自体を変更せずに最後の行だけを削除したい場合

sed -e '$ d' foo.txt

入力ファイルの最後の行自体を削除したい場合

sed -i '' -e '$ d' foo.txt

28
manpreet singh

Macユーザーの場合:

Macでは、head -n -1は機能しません。そして、私は(処理時間を心配せずに) "head"や "tail"コマンドだけを使ってこの問題を解決する簡単な解決策を見つけようとしていました。

私は以下の一連のコマンドを試してみましたが、[tail]コマンドを[Macで利用可能なオプションで]使用するだけで解決できたことを嬉しく思います。あなたがMacを使用していて、この問題を解決するために "tail"だけを使いたいのであれば、このコマンドを使うことができます。

猫file.txt | tail -r | tail -n + 2 | tail -r

説明 :

1> tail -r:単に入力の行の順番を逆にする

2> tail -n + 2:入力の2行目から始まるすべての行を印刷します。

24
Sarfraaz Ahmed
echo -e '$d\nw\nq'| ed foo.txt
12
lhf
awk 'NR>1{print buf}{buf = $0}'

基本的に、このコードは次のように言っています。

最初の行以降の各行について、バッファ行を印刷します。

各行について、バッファをリセットする

バッファは1行遅れているので、1行目からn-1行目を印刷することになります。

8
Foo Bah
awk "NR != `wc -l < text.file`" text.file |> text.file

このスニペットはトリックを行います。

0
Michael Kingski

これを手動で行う方法は次のとおりです(ファイルの最後の行をすばやく削除する必要がある場合、私は個人的にこの方法をよく使用します)。

vim + [FILE]

そこにある+記号は、ファイルがvimテキストエディターで開かれたときに、カーソルがファイルの最終行に配置されることを意味します。

キーボードでdを2回押すだけです。これはまさにあなたが望むことをします-最後の行を削除します。その後、:に続いてxを押し、次にEnterを押します。これにより、変更が保存され、シェルに戻ります。これで、最後の行が正常に削除されました。

0
Michael Rybkin

これらの解決策はどちらも他の形式です。私はこれらがもう少し実用的、明確、そして有用であることを見出しました:

Ddを使う:

BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
dd if=${ORIGINALFILE} of=${ORIGINALFILE}.tmp status=none bs=1 count=$(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc )
/bin/mv -f ${ORIGINALFILE}.tmp ${ORIGINALFILE}

切り捨ての使用

BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}
0
virtual-light