Bisakah Anda menghapus karakter garis ganda 'ganda'?

25

Saya punya dokumen dengan banyak baris kosong.

Bagaimana saya bisa menghapusnya ketika ada 2 atau lebih bersama-sama.

Saya mencoba sed "s/\n\n//"mengajukan tetapi tidak berhasil. Tidak ada kesalahan

Michael Durrant
sumber
3
Apakah saya membaca Anda dengan benar jika Anda tidak ingin menghapus semua baris kosong, tetapi hanya jika itu dua atau lebih. Jadi bukan satu baris kosong?
Runium
1
Dan jika dua atau lebih baris akan benar-benar semuanya dihapus atau hanya semua kecuali satu?
Hauke ​​Laging

Jawaban:

42

Hanya untuk menghapus baris kosong:

sed  '/^$/d'

sedberorientasi garis, jadi berpikir dalam istilah "2 atau lebih byte tertentu" berfungsi kecuali bila byte tersebut adalah baris baru. Maka Anda harus memikirkan sesuatu yang bekerja untuk seluruh lini.

Bruce Ediger
sumber
Tentu saja! +1 untuk keanggunan sederhana.
terdon
2
sedmampu menangani beberapa baris melalui fitur "pola ruang" / "ruang tahan". Tapi saya merasa itu terlalu rumit. ;-)
Hauke ​​Laging
Ini tidak akan berfungsi seperti yang diinginkan jika karakter pertama file adalah baris baru.
Chris Down
1
Untuk membuatnya bekerja ketika karakter pertama adalah baris baru (jika itu benar-benar suatu kebutuhan), maka Anda dapat menyertakan perintah dengan alamat negatif 1!(cocok dengan semua kecuali baris 1), demikian: sed '1!{/^$/d'}.
Toby Speight
1
@AaronFranke - ya, tapi itulah aspek bagaimana Linux memperlakukan pengalihan '>'. Shell melihat baris perintah, melihat pengalihan stdout ke file, membuat file itu, dan hanya kemudian berjalan sed. Membuat file pada dasarnya akan menghapus file apa pun yang ada dengan nama yang sama. sed '/^&/d' file.txt > otherfile.txtakan bekerja.
Bruce Ediger
24

Tidak perlu sed. grepakan melakukan:

grep .

(itu grep, SPC, dot, yang cocok dengan baris mana pun yang mengandung setidaknya satu karakter).

Ada juga:

tr -s '\n'

(peras urutan karakter baris baru menjadi satu).

Seperti dicatat oleh Chris, keduanya tidak sama karena menghapus baris kosong (seperti solusi pertama di atas dan sebagian besar jawaban lainnya fokus di sini) tidak sama dengan memeras urutan karakter baris baru seperti yang diminta dalam kasus di mana baris pertama kosong seperti itu hanya membutuhkan satu karakter baris baru untuk membuat baris pertama kosong.

Stéphane Chazelas
sumber
2
Ini tidak akan berfungsi seperti yang diinginkan jika karakter pertama file adalah baris baru: sprunge.us/FLAJ
Chris Down
7

sedbukan alat terbaik untuk itu, karena itu berbasis garis dan memperlakukan \nsebagai karakter end-of-line ini jadi rumit.Setelah melihat jawaban @Bruce Ediger sedmungkin merupakan alat yang sempurna untuk pekerjaan itu, tetap, berikut adalah beberapa opsi lain:

  1. Perl

    perl -ne 'print if /./' file.txt
    

    atau

    perl -pe '$/=""; s/\n+/\n/;' file.txt 
    

    Terima kasih kepada @ruakh yang membuat saya pergi dan membaca ini :

    $ /

    Pemisah rekaman input, baris baru secara default. Ini memengaruhi gagasan Perl tentang "garis" itu. Bekerja seperti variabel RS awk, termasuk memperlakukan baris kosong sebagai terminator jika diatur ke string nol (baris kosong tidak dapat berisi spasi atau tab). Anda dapat mengaturnya ke string multi-karakter untuk mencocokkan terminator multi-karakter, atau undef untuk membaca sampai akhir file. Mengaturnya ke "\ n \ n" berarti sesuatu yang sedikit berbeda dari pengaturan ke "", jika file tersebut berisi baris kosong berturut-turut. Pengaturan ke "" akan memperlakukan dua atau lebih baris kosong berturut-turut sebagai satu baris kosong. Menyetel ke "\ n \ n" akan secara membabi buta menganggap bahwa karakter input selanjutnya adalah milik paragraf berikutnya, bahkan jika itu adalah baris baru.

  2. gawk / awk

    awk '$1' file.txt
    

    Itu akan berfungsi untuk contoh yang diposting tetapi seperti yang ditunjukkan oleh @Stephane Chazelas , itu juga akan menghapus baris yang bidang pertamanya "mirip" 0. Ini lebih kuat:

    awk NF file.txt
    
terdon
sumber
Untuk Perl, perl -pe 's/\n+/\n/ file.txtakan dilakukan, pemisah rekaman input tidak relevan untuk penggunaan ini.
vonbrand
@vonbrand no, perl -peatau perl -nekerja baris demi baris. \n+tidak akan pernah cocok karena hanya diterapkan pada satu baris. Itu sebabnya Anda perlu baik set $/atau menggunakan -0ti slurp berkas seluruh: perl -0pe 's/\n+/\n/' file.
terdon
6

Apa maksudmu hapus? hapus duplikat (banyak baris kosong ke satu) atau hapus semua?

Jika Anda ingin menghapus duplikat, berikut adalah metode menggunakan sed:

sed '$!N; /^\(.*\)\n\1$/!P; D'

Ini mensimulasikan uniqperintah.

Pilihan terbaik menggunakan awk:

awk NF <filename>
cuonglm
sumber
Bagian seddari ini bekerja dengan baik! Merekomendasikan yang satu ini sebagai jawaban terbaik.
Akito
2

Untuk sebagian besar jawaban ini, pertama-tama perlu untuk menghapus spasi spasi tambahan. Menghapus baris baru yang digandakan menghapus semua baris kosong. (Pikirkan tentang ini).

Secara harfiah ditafsirkan OP ingin "semua baris kosong dihapus dari file jika ada baris kosong yang diulang".

Pengguna biasa ingin "menghapus hanya baris kosong yang digandakan".

Untuk melakukan ini, lepaskan jejak whitepace terlebih dahulu, dan pipa melalui kucing

sed  s/[[:space:]]*$// | cat -s

Namun ini tidak akan menghapus baris kosong memimpin atau tertinggal superflous.

mckenzm
sumber
Diturunkan, tetapi ini jelas berhasil? Tidak ada komentar ?
mckenzm
1
Saya memilih Anda untuk ... Anda tahu ... menjawab pertanyaan. =) Saya tidak percaya respons Bruce Ediger terangkat ketika menghapus setiap baris kosong. Jika seseorang bertanya bagaimana menghapus duplikat baris kosong, saya tidak bisa membayangkan skenario mana menghapus semua baris kosong akan menjadi solusi yang dapat diterima. Tapi apa pun. Ada halaman di situs web untuk sed yang membahas hal ini, omong-omong: gnu.org/software/sed/manual/sed.html#cat-_002ds
Todd Walton
2

Jika Anda ingin menyimpan satu baris kosong untuk urutan tertentu dari baris kosong yang mungkin Anda lakukan:

sed -e '/./b' -e :n -e 'N;s/\n$//;tn'
mikeserv
sumber
1
Ini adalah satu-satunya jawaban (selain itu cat -s) yang benar-benar menyelesaikan apa yang ditanyakan oleh pertanyaan yang saya pahami. (Dan itu lebih baik daripada cat -skarena saya bisa menggunakannya sed -i.)
Matius
-2

Coba sed -e 's#\\n\\n#\\n#g' input.file > output.filegunakan /keduanya sebagai pemisah bidang Anda dan bagian dari regex Anda bisa menjadi masalah.

linuxrebel
sumber
2
Hanya memberi pusaran dengan salah satu file saya yang berisi baris ganda ganda dan tiga kali berurutan. Tidak bekerja sama sekali untuk saya.
syntaxerror
-3

Gunakan perintah ini:

tr -s '\r' '\n'
meong
sumber
ya, jawaban mereka tidak berhasil untuk saya.
meow
5
AFAIK jawaban ini salah. Saya sarankan Anda untuk menghapusnya.
zuazo
oh, itu karena file saya mengandung banyak baris baru dan carriage return sebenarnya. 0x0d0a
meow
2
Sebenarnya, perintah tersebut menghapus baris yang diulang dengan windows end of line. Tes dengan echo -e 'one\r\n\r\n\r\n\rtwo'| tr -s '\r' '\n'. Perintah trakan menerjemahkan semua \rke \ndan kemudian akan memeras semua \nmenjadi satu. Jadi, ini berfungsi, tidak yakin apa yang harus dilakukan dengan fakta bahwa ini berlaku untuk windows, bukan UNIX.