Bagaimana cara menghapus setiap baris kedua dari suatu file?


25

Mengajukan:

Data inserted into table. Total count 13
No error occurred
Data inserted into table. Total count 45
No error occurred
Data inserted into table. Total count 14
No error occurred
Data inserted into table. Total count 90
No error occurred

File output yang diharapkan:

Data inserted into table. Total count 13
Data inserted into table. Total count 45
Data inserted into table. Total count 14
Data inserted into table. Total count 90

Saya ingin output terlihat seperti ini: setiap baris kedua akan dihapus tetapi tidak akan ada celah di antara baris.


5
Apakah Anda ingin menghapus setiap baris kedua atau semua baris yang berisi "Tidak ada kesalahan terjadi" ? Bagaimana jika dua baris berturut-turut memiliki "Tidak ada kesalahan terjadi" ?
Tulains Córdova

1
@ user1598390 Saya pikir ... dalam hal grep -v "No error occurred" fileini perintah ini harus berfungsi ... apa yang telah dijawab @paul. Dalam file output, tidak akan ada baris yang mengandung "Tidak ada kesalahan terjadi" bagian ini.
pmaipmui

1
Maka judul pertanyaan itu menyesatkan.
Tulains Córdova

Jawaban:


36

Dengan sed:

sed -e n\;d <file

Dengan POSIX awk:

awk 'FNR%2' <file

Jika Anda lebih tua awk(seperti oawk), Anda perlu:

oawk 'NR%2 == 1' <file

Dengan ex:

$ ex file <<\EX
:g/$/+d
:wq!
EX

akan mengedit file di tempat.

  • g tandai perintah global
  • /$/ cocokkan setiap baris
  • +d hapus baris berikutnya
  • wq! simpan semua perubahan

Pendekatan ini berbagi ideal yang sama dengan sedpendekatan, hapus setiap baris berikutnya dari baris saat ini mulai dari baris 1.

Dengan perl:

perl -ne 'print if $. % 2' <file

dan perl6:

perl6 -ne '.say if $*IN.ins % 2' <file
perl6 -ne '.say if ++$ % 2' <file

Ya ... ini berfungsi ... :) ... yang pertama berhasil .... saya juga sudah mencoba yang kedua .. ini mengatakan `awk: sintaks kesalahan line1 awk: bailing out near line 1 '
pmaipmui

sed -en \; d <file ~ Ya itu berfungsi @cuonglm ...
pmaipmui

1
Saya menduga Anda menggunakan n\;dalih-alih 'n;d'menyimpan karakter yang berharga tetapi logika itu keluar dari jendela saat Anda tidak perlu menggunakan -esakelar dan pengalihan file <!
Tom Fenech

1
@ Geek: Ini hanya versi yang lebih pendek sed -e 'n;d', menghemat satu karakter.
cuonglm

1
@ Geek: nperintah tulis pola spasi ke output standar jika -ndigunakan, lalu ganti spasi pola dengan baris berikutnya. Inilah setiap garis ganjil yang akan dicetak n, bahkan garis kemudian dibaca ke dalam ruang pola tetapi hapus segera dengan dperintah`.
cuonglm

62

Memecahkan ini dengan menghapus setiap baris kedua bisa menjadi rawan kesalahan (misalnya, ketika proses kadang-kadang menghasilkan dua baris yang bermakna, bukan satu). Mungkin lebih baik menyaring sampah:

grep -v "No error occurred" file

Itu dapat dijalankan sebagai filter, Anda dapat menambahkan lebih banyak pola sampah di sini dan meningkatkan hasilnya.


9
+1 untuk menunjukkan bahwa terkadang baris kedua penting!
Kaz Wolfe

12

Ассоrding ke pertanyaan, dengan GNU sed:

sed '0~2d' file

akan menghapus setiap baris kedua tetapi saya ingin menawarkan baris filter dengan isinya:

sed '/Data/! d' file

atau dengan hasil yang sama

sed '/No error/d' file

sed '/ No error / d' file ~ memberikan output yang diinginkan @ Costas
pmaipmui

5
Perhatikan bahwa dua yang terakhir adalah cara berbelit-belit untuk menulis grep Datadangrep -v 'No error'
Stéphane Chazelas

5

Berikut cara menggunakan sed:

sed -n 'p;n' filename

Cara lain dengan GNU sed:

sed -n '1~2p' filename

Output dari perintah di atas:

Data inserted into table. Total count 13
Data inserted into table. Total count 45
Data inserted into table. Total count 14
Data inserted into table. Total count 90

Apa maksudmu saat mengatakan shortest way using sed?
cuonglm

Apa alasan gperintahnya? sed -n 'p;n'cukup.
Costas

@cuonglm: Maksud saya cara sederhana untuk melakukan. Omong-omong menghapus kata itu. :)
serenesat

@ Costas: Terima kasih! Baru diperiksa, ini bekerja tanpa g. dihapus g dari perintah. :)
serenesat

4

Anda dapat mencoba dengan awk:

awk 'NR % 2 != 0' file

atau Anda hanya dapat mencetak garis yang mengandung Data inserted:

awk '$0 ~ /Data inserted/' file

Saya telah mencoba jawaban Anda berdua dan keduanya bekerja ... :)
pmaipmui

3

Jawaban lain, Anda bisa menggunakan vi / vim!

qdjddq

Dan kemudian jika file Anda adalah 500 baris (misalnya) ketik

250 @ d

Dan kemudian untuk menulis dan keluar ketik

: x

Atau jika terjadi kesalahan dan Anda tidak ingin menyimpan:

: q!

Penjelasan:

q      #Start Recording
 d     #Put the recording into register 'd'
  j    #Move the cursor down
   dd  #Delete the line
     q #Stop recording


250    #Number of repeats
   @d  #Playback the recording in register 'd'.

2

Berikut cara yang berbeda untuk melakukannya:

< file paste - - | cut -f1

Ini mengasumsikan bahwa garis bernomor ganjil tidak mengandung tab. Jika ya, maka Anda harus memilih karakter pemisah lain, misalnya di :sini:

< file paste -d: - - | cut -d: -f1

1
Saya memikirkan hal ini ketika pertama kali melihat pertanyaan ... Akan menarik untuk menjalankan tes kecepatan seddengan file besar (mis. 20 mil baris). Bagaimanapun, +1 tetapi sebenarnya, untuk menghindari sakit kepala, pilih pembatas yang tidak mungkin terjadi dalam file teks, seperti $'\002'...
don_crissti

@don_crissti ya penggunaan karakter non-cetak untuk pemisah adalah ide bagus. Dan ya, ini terukur lebih cepat daripada solusi sed. Saya membuat file uji dengan seq 100000000 > 100mil.txt. The paste|cutsolusi selesai dalam waktu sekitar 7,5 detik, vs hampir 12 untuk sedsolusi. Tampaknya bisa diulang. greplebih cepat. Ubuntu 14.04 dengan alat GNU standar.
Digital Trauma

Yap, paste+ cutsangat dioptimalkan untuk pekerjaan mereka sehingga tidak mengherankan kombinasi mereka sangat cepat ...
don_crissti


0

Ini juga memecahkan masalah, meskipun sedikit lebih lambat:

vim -c "%normal jdd" -c "wq" file
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.