Hapus nomor baris tertentu dari file teks menggunakan sed?

235

Saya ingin menghapus satu atau lebih nomor baris tertentu dari file. Bagaimana saya melakukan ini dengan menggunakan sed?

Justin Ethier
sumber
1
Bisakah Anda memberikan contoh yang lebih spesifik tentang apa yang Anda inginkan? Bagaimana Anda memutuskan jalur mana yang akan dihapus?
Mark Byers
Mungkin lihat juga stackoverflow.com/questions/13272717/… dan hanya berlaku secara terbalik (cetak jika kunci tidak dalam array asosiatif).
tripleee

Jawaban:

374

Jika Anda ingin menghapus baris 5 hingga 10 dan 12:

sed -e '5,10d;12d' file

Ini akan mencetak hasilnya ke layar. Jika Anda ingin menyimpan hasil ke file yang sama:

sed -i.bak -e '5,10d;12d' file

Ini akan mendukung file hingga file.bak, dan menghapus baris yang diberikan.

Catatan: Nomor baris dimulai dari 1. Baris pertama file adalah 1, bukan 0.

Brian Campbell
sumber
32
Tidak semua unix memiliki gnu sed dengan "-i". Jangan membuat kesalahan dengan kembali ke "sed cmd file> file", yang akan menghapus file Anda.
pra
4
bagaimana Jika saya ingin menghapus baris ke-5 hingga ke baris terakhir?
Jürgen Paul
14
@WearetheWorldsed -e '5,$d' file
Brian Campbell
1
@BrianCampbell Apa yang harus saya lakukan untuk menghapus hanya garis tertentu ??
Kanagavelu Sugumar
14
@ KanagaveluSugumar sed -e '5d' file. Sintaksnya adalah <address><command>; di mana <address>bisa berupa baris tunggal suka 5atau rentang garis seperti 5,10, dan perintah dmenghapus baris atau garis yang diberikan. Alamat juga bisa berupa ekspresi reguler, atau tanda dolar yang $menunjukkan baris terakhir file.
Brian Campbell
50

Anda dapat menghapus satu baris tertentu dengan nomor barisnya dengan

sed -i '33d' file

Ini akan menghapus baris pada nomor 33 baris dan menyimpan file yang diperbarui.

ya
sumber
1
Dalam kasus saya "sed" menghapus garis yang salah. Jadi saya menggunakan pendekatan ini: sed -i '0,/<TARGET>/{/<NEW_VALUE>/d;}' '<SOME_FILE_NAME>'. Terima kasih!
Eduardo Lucio
Sama di sini, saya menulis satu lingkaran dan anehnya beberapa file kehilangan baris yang benar tetapi beberapa file kehilangan satu baris lain juga, tidak tahu apa yang salah. (GNU / Linux bash4.2) perintah awk di bawah ini bekerja dengan baik dalam lingkaran
FatihSarigol
Berhati-hatilah untuk menggunakan sort -r jika Anda menghapus dari daftar baris, jika tidak sed pertama Anda akan mengubah nomor baris dari semua yang lain! ...
Konchog
Untuk komentar tentang baris yang salah dihapus dalam satu loop: pastikan untuk memulai dengan nomor baris terbesar, jika tidak setiap baris yang dihapus akan mengimbangi penomoran baris ...
Skippy le Grand Gourou
25

dan juga canggung

awk 'NR!~/^(5|10|25)$/' file
ghostdog74
sumber
2
NB: Baris awk itu bekerja lebih andal bagi saya daripada varian sed (antara OS-X dan Ubuntu Linux)
Jay Taylor
3
Perhatikan bahwa ini tidak menghapus apa pun dalam file. Itu hanya mencetak file tanpa garis-garis ini ke stdout. Jadi, Anda juga perlu mengarahkan output ke file temp, dan kemudian memindahkan file temp untuk mengganti yang asli.
mivk
17
$ cat foo
1
2
3
4
5
$ sed -e '2d;4d' foo
1
3
5
$ 
Matthew Slattery
sumber
6

Ini sangat sering merupakan gejala antipattern. Alat yang menghasilkan nomor baris dapat diganti dengan yang menghapus garis segera. Sebagai contoh;

grep -nh error logfile | cut -d: -f1 | deletelines logfile

(Di mana deletelinesutilitas yang Anda bayangkan Anda butuhkan) adalah sama dengan

grep -v error logfile

Karena itu, jika Anda berada dalam situasi di mana Anda benar-benar perlu melakukan tugas ini, Anda dapat menghasilkan sedskrip sederhana dari file nomor baris. Dengan lucu (tapi mungkin sedikit membingungkan) Anda dapat melakukan ini sed.

sed 's%$%d%' linenumbers

Ini menerima file nomor baris, satu per baris, dan menghasilkan, pada output standar, nomor baris yang sama dengan dditambahkan setelah masing-masing. Ini adalah sedskrip yang valid , yang dapat kita simpan ke file, atau (pada beberapa platform) pipa ke sedcontoh lain :

sed 's%$%d%' linenumbers | sed -f - logfile

Pada beberapa platform, sed -ftidak memahami argumen opsi -berarti input standar, jadi Anda harus mengarahkan ulang skrip ke file sementara, dan membersihkannya ketika Anda selesai, atau mungkin mengganti dasbor tunggal dengan /dev/stdinatau /proc/$pid/fd/1jika OS Anda (atau shell ) memiliki itu.

Seperti biasa, Anda dapat menambahkan -isebelum -fopsi untuk sedmengedit file target, alih-alih menghasilkan hasilnya pada output standar. Pada platform * BSDish (termasuk OSX) Anda juga perlu memberikan argumen eksplisit -i; idiom yang umum adalah memberikan argumen kosong; -i ''.

tripleee
sumber
Saya tidak begitu setuju dengan "gejala antipattern". Jenis file berbasis markup (mis. XML atau JSON) memerlukan baris tertentu di akhir agar menjadi file yang valid. Dalam hal ini, seringkali merupakan pendekatan yang paling masuk akal untuk menghapus garis-garis itu, memasukkan ke dalam file apa yang ingin Anda tambahkan dan kemudian menambahkan kembali garis-garis itu, karena menempatkan garis-garis di antara garis lurus bisa jauh lebih sulit, dan bertentangan dengan keinginan potensial untuk menghindari alat-alat tambahan seperti sed sebanyak yang Anda bisa.
Egor Hans
Saya tidak begitu mengerti skenario seperti apa yang Anda bayangkan. Ada yang skenario di mana ini merupakan pendekatan yang sah namun sebagian besar kasus yang saya lihat adalah pemula yang melakukan lebih atau kurang persis apa contoh pertama saya menunjukkan. (Mungkin mereka berasal dari bahasa tingkat rendah dan digunakan untuk membagi masalah mereka melewati tingkat molekuler, karena Anda harus dalam asm atau C.)
tripleee
Menghapus hal dengan nomor baris dari XML atau JSON terdengar extermely rapuh, jika tidak langsung berbahaya.
tripleee
Apa yang saya maksud dengan itu pada dasarnya, adalah bahwa sebagai pencipta file seperti itu, Anda tahu apa yang harus ada di akhir dokumen (yaitu set kurung kurawal / kurung siku dalam beberapa baris terakhir untuk JSON, atau tepatnya tag penutup untuk XML). Menyadari hal itu, pendekatan paling sederhana untuk memperluas dokumen semacam itu adalah 1) menghapus beberapa baris terakhir, 2) menambahkan konten baru, 3) menambahkan kembali beberapa baris terakhir. Dengan cara ini, dokumen dapat valid baik sebelum dan sesudah diperpanjang, tanpa perlu mencari cara untuk menambahkan baris di tengah dokumen.
Egor Hans
1
Sejauh ini ini adalah satu-satunya jawaban dengan solusi yang sesuai untuk sejumlah besar baris (yaitu disediakan oleh file). Dan kata pengantar juga masuk akal. Layak lebih banyak upvotes. BTW, jika Anda ingin mencetak garis daripada menghapusnya, gunakan psebagai ganti d, bersama dengan opsi -n(itu tidak akan berfungsi tanpa -n, dan !dtidak akan berfungsi baik).
Skippy le Grand Gourou
2

Saya ingin mengusulkan generalisasi dengan awk.

Ketika file dibuat dengan blok dengan ukuran tetap dan baris yang akan dihapus diulang untuk setiap blok, awk dapat berfungsi dengan baik sedemikian rupa

awk '{nl=((NR-1)%2000)+1; if ( (nl<714) || ((nl>1025)&&(nl<1029)) ) print  $0}'
 OriginFile.dat > MyOutputCuttedFile.dat

Dalam contoh ini ukuran untuk blok adalah 2000 dan saya ingin mencetak garis [1..713] dan [1026..1029].

  • NR adalah variabel yang digunakan oleh awk untuk menyimpan nomor baris saat ini.
  • % memberikan sisa (atau modulus) pembagian dua bilangan bulat;
  • nl=((NR-1)%BLOCKSIZE)+1Di sini kita menulis dalam variabel nl nomor baris di dalam blok saat ini. (Lihat di bawah)
  • ||dan &&operator logis OR dan DAN .
  • print $0 menulis baris penuh

Why ((NR-1)%BLOCKSIZE)+1:
(NR-1) We need a shift of one because 1%3=1, 2%3=2, but 3%3=0.
  +1   We add again 1 because we want to restore the desired order.

+-----+------+----------+------------+
| NR  | NR%3 | (NR-1)%3 | (NR-1)%3+1 |
+-----+------+----------+------------+
|  1  |  1   |    0     |     1      |
|  2  |  2   |    1     |     2      |
|  3  |  0   |    2     |     3      |
|  4  |  1   |    0     |     1      |
+-----+------+----------+------------+

Cepat
sumber
2
Saya mengagumi cara Anda menghayati nama gila Anda.
Jukka Dahlbom