Jika "besar" itu berarti sekitar 10 juta baris atau lebih, lebih baik digunakan tail. Tidak dapat mengedit di tempat, tetapi kinerjanya membuat kekurangan itu dapat dimaafkan:
tail -n +2 large_file > large_file.new
Edit untuk menunjukkan beberapa perbedaan waktu:
( awkkode oleh Jaypal ditambahkan untuk memiliki waktu eksekusi pada mesin yang sama (CPU 2.2GHz).)
bash-4.2$ seq 1000000 > bigfile.txt # further file creations skipped
bash-4.2$ time sed -i 1d bigfile.txt
time 0m4.318s
bash-4.2$ time ed -s <<< $'1d\nwq' bigfile.txt
time 0m0.533s
bash-4.2$ time perl -pi -e 'undef$_ if$.==1' bigfile.txt
time 0m0.626s
bash-4.2$ time { tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt; }
time 0m0.034s
bash-4.2$ time { awk 'NR>1 {print}' bigfile.txt > newfile.txt && mv -f newfile.txt bigfile.txt; }
time 0m0.328s
Dalam hal ini tail, saya lebih suka menghitung waktu untuk melakukan keduanya menghapus baris pertama dan ganti bigfile.txtdengan bigfile.new.
rozcietrzewiacz
@rozcietrzewiacz, poin Anda sudah benar. Terima kasih. Diperbarui.
manatwork
Ini sangat keren! Saya melakukan hal yang sama dengan awkdan mendapatkan hasil berikut -[jaypal:~/Temp] seq 1000000 > bigfile.txt [jaypal:~/Temp] time awk 'NR>1 {print}' bigfile.txt >newfile.txt real 0m0.649s user 0m0.601s sys 0m0.033s
jaypal singh
1
@ Jaypal, saya menambahkan kode Anda ke daftar alternatif. Di mesin saya itu bahkan lebih cepat. Aneh, saya berharap awkkinerja lebih dekat sed. (Catatan untuk diri saya sendiri: jangan pernah mengharapkan - sebagai gantinya.)
manatwork
Ini adalah solusi terbaik dalam kasus saya: tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt;Saya menggunakan satu file dengan kunci untuk melacak daftar tugas tunggal yang digunakan oleh banyak proses. Saya mulai dengan apa poster awal yang digunakan: sed -i 1d large_file . Itu menyebabkan file terkunci selama 1-2 detik. The tail/mvcombo melengkapi hampir seketika. Terima kasih!
Chris Adams
6
Tidak ada cara untuk secara efisien menghapus sesuatu dari awal file. Menghapus data dari awal memerlukan penulisan ulang seluruh file.
Memotong dari ujung file bisa sangat cepat (OS hanya harus menyesuaikan informasi ukuran file, mungkin membersihkan blok yang sekarang tidak digunakan). Ini umumnya tidak mungkin ketika Anda mencoba untuk menghapus dari kepala file.
Secara teori ini bisa menjadi "cepat" jika Anda menghapus seluruh blok / luas tepat, tetapi tidak ada panggilan sistem untuk itu, jadi Anda harus mengandalkan semantik khusus sistem berkas (jika ada). (Atau memiliki beberapa bentuk offset di dalam blok / batas pertama untuk menandai awal sebenarnya file, saya kira. Tidak pernah mendengarnya juga.)
Jika file tersebut sangat besar, I / O overhead kemungkinan (mungkin jauh) lebih besar daripada overhead CPU yang diperlukan untuk memproses akhir baris.
Mat
Kamu benar. Namun mungkin ada perbedaan dalam cara alat mengakses konten file. Yang terbaik adalah tidak memproses baris demi baris saat tidak perlu atau setidaknya tidak membaca baris demi baris saat tidak perlu.
manatwork
2
Saya terkejut perbedaannya begitu besar dalam hasil Anda, dan dapat mereproduksinya dengan ukuran file itu di sini. Manfaatnya tampaknya berkurang karena ukuran file meningkat (dicoba dengan seq 10M, 15s untuk sed, 5s untuk ed). Tetap tips yang bagus (+1).
Mat
Dimulai dengan versi 3.15, Linux sekarang memiliki API untuk meruntuhkan bagian-bagian file pada sistem file berbasis luas, tetapi setidaknya untuk ext4 yang hanya dapat dilakukan pada blok penuh (biasanya 4k).
Stéphane Chazelas
Bahkan jika pengeditan mengharuskan penulisan ulang seluruh file, terkadang sangat berguna untuk memiliki alat baris perintah untuk mengedit secara efisien. Dalam kasus saya, ini membantu ketika saya harus menghapus baris pertama dari file yang lebih besar dari total RAM sistem saya.
Jason
3
Metode yang paling efisien, jangan lakukan itu! Jika Anda melakukannya, Anda perlu dua kali ruang 'besar' pada disk, dan Anda membuang IO.
Jika Anda terjebak dengan file besar yang ingin Anda baca tanpa baris 1, tunggu sampai Anda perlu membacanya untuk menghapus baris 1. Jika Anda perlu mengirim file dari stdin ke suatu program, gunakan tail untuk melakukannya:
tail -n +2 | your_program
Saat Anda perlu membaca file, Anda dapat mengambil kesempatan untuk menghapus baris 1, tetapi hanya jika Anda memiliki ruang yang dibutuhkan pada disk:
tail -n +2 | tee large_file2 | your_program
Jika Anda tidak dapat membaca dari stdin, gunakan fifo:
yang lebih baik lagi jika Anda menggunakan bash, manfaatkan penggantian proses:
your_program -i <(tail -n +2 large_file)
Jika Anda perlu mencari dalam file, saya tidak melihat solusi yang lebih baik daripada tidak terjebak dengan file di tempat pertama. Jika file ini dihasilkan oleh stdout:
large_file_generator | tail -n +2 > large_file
Selain itu, selalu ada solusi pengganti fifo atau proses:
Sistem file khusus (diimplementasikan menggunakan FUSE atau mekanisme serupa) dapat mengekspos direktori yang isinya persis sama dengan direktori yang sudah ada di tempat lain, tetapi dengan file terpotong sesuai keinginan. Sistem file akan menerjemahkan semua offset file. Maka Anda tidak perlu melakukan penulisan ulang file yang memakan waktu.
Tetapi mengingat ide ini sangat tidak sepele, kecuali Anda punya puluhan terabyte file seperti itu, menerapkan sistem file seperti itu akan terlalu mahal / memakan waktu untuk menjadi praktis.
tail
, saya lebih suka menghitung waktu untuk melakukan keduanya menghapus baris pertama dan gantibigfile.txt
denganbigfile.new
.awk
dan mendapatkan hasil berikut -[jaypal:~/Temp] seq 1000000 > bigfile.txt [jaypal:~/Temp] time awk 'NR>1 {print}' bigfile.txt >newfile.txt real 0m0.649s user 0m0.601s sys 0m0.033s
awk
kinerja lebih dekatsed
. (Catatan untuk diri saya sendiri: jangan pernah mengharapkan - sebagai gantinya.)tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt;
Saya menggunakan satu file dengan kunci untuk melacak daftar tugas tunggal yang digunakan oleh banyak proses. Saya mulai dengan apa poster awal yang digunakan:sed -i 1d large_file
. Itu menyebabkan file terkunci selama 1-2 detik. Thetail/mv
combo melengkapi hampir seketika. Terima kasih!Tidak ada cara untuk secara efisien menghapus sesuatu dari awal file. Menghapus data dari awal memerlukan penulisan ulang seluruh file.
Memotong dari ujung file bisa sangat cepat (OS hanya harus menyesuaikan informasi ukuran file, mungkin membersihkan blok yang sekarang tidak digunakan). Ini umumnya tidak mungkin ketika Anda mencoba untuk menghapus dari kepala file.
Secara teori ini bisa menjadi "cepat" jika Anda menghapus seluruh blok / luas tepat, tetapi tidak ada panggilan sistem untuk itu, jadi Anda harus mengandalkan semantik khusus sistem berkas (jika ada). (Atau memiliki beberapa bentuk offset di dalam blok / batas pertama untuk menandai awal sebenarnya file, saya kira. Tidak pernah mendengarnya juga.)
sumber
Metode yang paling efisien, jangan lakukan itu! Jika Anda melakukannya, Anda perlu dua kali ruang 'besar' pada disk, dan Anda membuang IO.
Jika Anda terjebak dengan file besar yang ingin Anda baca tanpa baris 1, tunggu sampai Anda perlu membacanya untuk menghapus baris 1. Jika Anda perlu mengirim file dari stdin ke suatu program, gunakan tail untuk melakukannya:
Saat Anda perlu membaca file, Anda dapat mengambil kesempatan untuk menghapus baris 1, tetapi hanya jika Anda memiliki ruang yang dibutuhkan pada disk:
Jika Anda tidak dapat membaca dari stdin, gunakan fifo:
yang lebih baik lagi jika Anda menggunakan bash, manfaatkan penggantian proses:
Jika Anda perlu mencari dalam file, saya tidak melihat solusi yang lebih baik daripada tidak terjebak dengan file di tempat pertama. Jika file ini dihasilkan oleh stdout:
Selain itu, selalu ada solusi pengganti fifo atau proses:
sumber
Anda dapat menggunakan Vim dalam mode Ex:
1
pilih baris pertamad
menghapusx
Simpan dan tutupsumber
Ini hanya berteori, tapi ...
Sistem file khusus (diimplementasikan menggunakan FUSE atau mekanisme serupa) dapat mengekspos direktori yang isinya persis sama dengan direktori yang sudah ada di tempat lain, tetapi dengan file terpotong sesuai keinginan. Sistem file akan menerjemahkan semua offset file. Maka Anda tidak perlu melakukan penulisan ulang file yang memakan waktu.
Tetapi mengingat ide ini sangat tidak sepele, kecuali Anda punya puluhan terabyte file seperti itu, menerapkan sistem file seperti itu akan terlalu mahal / memakan waktu untuk menjadi praktis.
sumber