Bagaimana cara menghapus baris tertentu (menggunakan nomor baris) dalam file?

27

Ada baris tertentu yang ingin saya hapus dari file. Katakanlah itu baris 20-37 dan kemudian baris 45. Bagaimana saya melakukannya tanpa menentukan isi dari baris-baris itu?

tepang
sumber
Seberapa besar file Anda? Mungkinkah itu dimuat ke dalam memori?
Faheem Mitha
Beberapa kilobyte.
tshepang

Jawaban:

29

Dengan sed, seperti:

sed '20,37d; 45d' < input.txt > output.txt

Jika Anda ingin melakukan ini di tempat:

sed --in-place '20,37d; 45d' file.txt
pdo
sumber
Apakah ada cara untuk melakukannya di tempat?
tshepang
Saya sarankan sed -i file
enzotib
1
@Tepanget: Gunakan ed, atau GNU -i, atau sponge, atau metode file besar .
Gilles 'SO- berhenti bersikap jahat'
3
Saya sering bertanya-tanya tentang istilah yang mungkin menyesatkan di tempat , ketika merujuk ke 'sed', jadi saya mencarinya di 'man sed': --in-place [= SUFFIX] This option specifies that files are to be edited in-place. GNU sed 'melakukan ini dengan membuat file sementara dan mengirim output ke file ini daripada ke output standar. `... Saya tidak tahu tentang 'sed' lain selain logistik memperbarui" di tempat "dengan editor aliran jangan" menghitung ":)
Peter.O
2
Sebagian besar metode "di tempat" menggunakan file sementara, menurut pengalaman saya.
Faheem Mitha
5

Jika file tersebut cocok dengan nyaman dalam memori, Anda juga bisa menggunakan ed.
Perintahnya sangat mirip dengan yang di sedatas dengan satu perbedaan penting : Anda harus melewati daftar nomor / rentang baris yang akan dihapus dalam urutan menurun (dari baris tertinggi / rentang ke terendah). Alasannya adalah bahwa ketika Anda menghapus / menyisipkan / membagi / bergabung dengan baris ed, buffer teks diperbarui setelah setiap sub-perintah sehingga jika Anda menghapus beberapa baris, sisa baris berikut tidak lagi berada pada posisi yang sama di buffer ketika subcommand berikutnya dijalankan. Jadi, Anda harus mulai mundur 1 . Pengeditan di
tempat :

ed -s in_file <<IN
45d
20,37d
w
q
IN

atau

ed -s in_file <<< $'45d\n20,37d\nw\nq\n'

atau

printf '%s\n' 45d 20,37d w q | ed -s in_file

Ganti writus dengan ,printisan jika Anda ingin mencetak hasil yang dihasilkan alih-alih menulis ke file. Jika Anda ingin menjaga file asli tetap utuh dan menulis ke file lain, Anda dapat meneruskan nama file baru ke wsub- perintah rite:

ed -s in_file <<IN
78,86d
65d
51d
20,37d
w out_file
q
IN

1 Kecuali Anda bersedia menghitung nomor baris baru setelah setiap delete, yang cukup sepele untuk kasus khusus ini (setelah menghapus baris 20-37, yaitu 18 baris, baris 45 menjadi baris 27) sehingga Anda dapat menjalankan:

ed -s in_file <<IN
20,37d
27d
w
q
IN

Namun, jika Anda harus menghapus beberapa nomor / rentang baris, bekerja mundur adalah no-brainer.

don_crissti
sumber
Apakah qperintah itu berguna pada akhirnya? Saya kira itu keluar baik cara.
Tom Fenech
@ TomFenech - tidak semua implementasi keluar dengan cara baik (meskipun kebanyakan ... Saya tidak dapat lagi menemukan utas tempat ini dibahas ...)
don_crissti
1

Cukup baca ke memori, ubah, lalu tulis kembali. Anda dapat melakukan sesuatu seperti

filename = "foo"
f = open(filename, 'r+')                                                                                                                                 
linenums = [1, 3]                                                                                                                                            
s = [y for x, y in enumerate(f) if x not in [line-1 for line in linenums]]                                                                                                                                          
f.seek(0)
f.write(''.join(s))
f.truncate(f.tell())
f.close()

Diuji dengan file 5 baris. Kredit untuk http://pleac.sourceforge.net/pleac_python/fileaccess.html , lihat bagian "Memodifikasi File di Tempat Tanpa File Sementara". Lihat juga /programming/125703/how-do-i-modify-a-text-file-in-python

Beberapa catatan:

  1. Pertama-tama orang dapat memotong file, kemudian menulis padanya, daripada menulis, kemudian memotong, seperti di atas. Namun, saya tidak tahu tentang bendera Python yang memungkinkan seseorang untuk membaca, dan kemudian melakukan penulisan terpotong. Tapi mungkin saya kehilangan sesuatu, karena dokumennya tidak begitu jelas. Yang membawaku ke

  2. Terkadang dokumen Python benar-benar payah. Lihat http://docs.python.org/library/functions.html#open

    Mode 'r +', 'w +' dan 'a +' membuka file untuk memperbarui (perhatikan bahwa 'w +' memotong file).

    Apakah ini ada artinya bagi Anda? Apa itu "terbuka untuk memperbarui"?

  3. Saya tidak tahu apakah melakukan ini dengan python sebagai lawan sesuatu yang aneh seperti editor aliran lebih baik. Mungkin lebih portabel, tapi saya tidak tahu seberapa sed portabel. Saya hanya menulis seperti itu karena saya lebih nyaman dengan pemrograman tingkat rendah daripada menggunakan alat unix klasik, yang bagus jika mereka melakukan apa yang Anda inginkan, tetapi (saya pikir) umumnya kurang fleksibel.

  4. Pendekatan ini (memanipulasi file dalam memori) memperdagangkan memori untuk ruang disk. Seharusnya berfungsi pada mesin dengan beberapa Gb memori untuk file hingga beberapa ratus Mb. Python tidak menangani string dengan sangat efisien, jadi beralih ke C / C ++ misalnya akan sedikit meningkatkan kinerja dan sangat mengurangi penggunaan memori.

Faheem Mitha
sumber
0

Anda dapat menggunakan Vim dalam mode Ex:

ex -sc '20,37d|45d|x' file
  1. d menghapus

  2. x Simpan dan tutup

Steven Penny
sumber