Saya punya file foo.txt
,, berisi baris-baris berikut:
a
b
c
Saya ingin perintah sederhana yang menghasilkan konten foo.txt
:
a
b
Saya punya file foo.txt
,, berisi baris-baris berikut:
a
b
c
Saya ingin perintah sederhana yang menghasilkan konten foo.txt
:
a
b
Jawaban:
Menggunakan GNU sed
:
sed -i '$ d' foo.txt
The -i
pilihan tidak ada di GNU sed
versi lebih tua dari 3,95, sehingga Anda harus menggunakannya sebagai filter dengan file sementara:
cp foo.txt foo.txt.tmp
sed '$ d' foo.txt.tmp > foo.txt
rm -f foo.txt.tmp
Tentu saja, dalam hal ini Anda juga bisa menggunakan head -n -1
bukan sed
.
MacOS:
Pada Mac OS X (pada 10.7.4), setara dengan sed -i
perintah di atas adalah
sed -i '' -e '$ d' foo.txt
$ d
regex. Ini adalah perintah sed. d
adalah perintah untuk menghapus sebuah baris, sementara itu $
berarti "baris terakhir dalam file". Saat menentukan lokasi (disebut "rentang" dalam istilah) sebelum perintah, perintah itu hanya diterapkan ke lokasi yang ditentukan. Jadi, perintah ini secara eksplisit mengatakan "dalam kisaran baris terakhir dalam file, hapus saja". Cukup licin dan langsung ke intinya, jika Anda bertanya kepada saya.
Sejauh ini, ini adalah solusi tercepat dan paling sederhana, terutama pada file besar:
head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt
jika Anda ingin menghapus baris teratas gunakan ini:
tail -n +2 foo.txt
yang berarti jalur keluaran mulai dari jalur 2.
Jangan gunakan sed
untuk menghapus garis dari atas atau bawah file - ini sangat lambat jika file tersebut besar.
head -n -1 foo.txt
sudah cukup
brew install coreutils
(utilitas inti GNU) dan menggunakannya ghead
sebagai gantinya head
.
FILE=$1; TAIL=$2; head -n -${TAIL} ${FILE} > temp ; mv temp ${FILE}
Jalankan untuk menghapus 4 baris misalnya dari myfile sebagai: ./TAILfixer myfile 4
tentu saja pertama-tama membuatnya dapat dijalankan olehchmod +x TAILfixer
sed
, perintah ini juga sangat lambat
Saya mengalami masalah dengan semua jawaban di sini karena saya bekerja dengan file BESAR (~ 300GB) dan tidak ada solusi yang diskalakan. Inilah solusi saya:
dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )
Dengan kata lain: Cari tahu panjang file yang ingin Anda buat (panjang file dikurangi panjang panjang baris terakhir, menggunakan bc
) dan, setel posisi itu menjadi akhir file (dengan memasukkan dd
satu byte /dev/null
ke Itu).
Ini cepat karena tail
mulai membaca dari akhir, dan dd
akan menimpa file di tempat daripada menyalin (dan mengurai) setiap baris file, yang merupakan solusi apa yang dilakukan oleh solusi lain.
CATATAN: Ini menghapus baris dari file di tempat! Buat cadangan atau uji pada file dummy sebelum mencobanya di file Anda sendiri!
Untuk menghapus baris terakhir dari file tanpa membaca seluruh file atau menulis ulang apa pun , Anda dapat menggunakan
tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}
Untuk menghapus baris terakhir dan juga mencetaknya di stdout ("pop" itu), Anda dapat menggabungkan perintah itu dengan tee
:
tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})
Perintah-perintah ini secara efisien dapat memproses file yang sangat besar. Ini mirip dengan, dan diilhami oleh, jawaban Yossi, tetapi ia menghindari penggunaan beberapa fungsi tambahan.
Jika Anda akan menggunakan ini berulang kali dan menginginkan penanganan kesalahan dan beberapa fitur lainnya, Anda dapat menggunakan poptail
perintah di sini:
https://github.com/donm/evenmoreutils
truncate
tidak tersedia pada OS X secara default. Tapi mudah untuk menginstal menggunakan Brew: brew install truncate
.
Pengguna Mac
jika Anda hanya ingin output baris terakhir dihapus tanpa mengubah file itu sendiri lakukan
sed -e '$ d' foo.txt
jika Anda ingin menghapus baris terakhir dari file input itu sendiri lakukan
sed -i '' -e '$ d' foo.txt
-i ''
memberitahu sed untuk memodifikasi file di tempat, sambil menyimpan cadangan dalam file dengan ekstensi yang disediakan sebagai parameter. Karena parameternya adalah string kosong, tidak ada file cadangan yang dibuat. -e
memberitahu sed untuk mengeksekusi perintah. Perintah itu $ d
berarti: cari baris terakhir ( $
) dan hapus ( d
).
Di Mac, head -n -1 tidak akan berfungsi. Dan, saya berusaha mencari solusi sederhana [tanpa khawatir tentang waktu pemrosesan] untuk menyelesaikan masalah ini hanya dengan menggunakan perintah "head" dan / atau "tail".
Saya mencoba urutan perintah berikut dan senang bahwa saya bisa menyelesaikannya hanya menggunakan perintah "tail" [dengan opsi yang tersedia di Mac]. Jadi, jika Anda menggunakan Mac, dan hanya ingin menggunakan "tail" untuk menyelesaikan masalah ini, Anda dapat menggunakan perintah ini:
cat file.txt | tail -r | tail -n +2 | ekor -r
1> tail -r: cukup membalik urutan garis dalam inputnya
2> tail -n +2: ini mencetak semua baris mulai dari baris kedua di inputnya
ghead -n -1
awk 'NR>1{print buf}{buf = $0}'
Pada dasarnya, kode ini mengatakan sebagai berikut:
Untuk setiap baris setelah yang pertama, cetak garis buffered
untuk setiap baris, setel ulang buffer
Buffer ditunda oleh satu baris, maka Anda akhirnya mencetak baris 1 ke n-1
awk "NR != `wc -l < text.file`" text.file |> text.file
Cuplikan ini berhasil.
Kedua solusi ini ada di sini dalam bentuk lain. Saya menemukan ini sedikit lebih praktis, jelas, dan berguna:
Menggunakan 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}
Menggunakan terpotong:
BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}
sed '$d' ~/path/to/your/file/name
sed -i '' -e '$ d' ~/path/to/your/file/name
Inilah cara Anda dapat melakukannya secara manual (saya pribadi sering menggunakan metode ini ketika saya perlu menghapus baris terakhir dalam sebuah file):
vim + [FILE]
Itu +
tanda ada berarti bahwa ketika file dibuka di editor teks vim, kursor akan diposisikan pada baris terakhir dari file.
Sekarang cukup tekan d
dua kali pada keyboard Anda. Ini akan melakukan apa yang Anda inginkan — hapus baris terakhir. Setelah itu, tekan :
diikuti oleh x
dan kemudian tekan Enter
. Ini akan menyimpan perubahan dan membawa Anda kembali ke shell. Sekarang, baris terakhir telah berhasil dihapus.
sed -i
perintah di atas adalahsed -i '' -e '$ d' foo.txt
. Selain itu,head -n -1
saat ini tidak akan berfungsi pada Mac.