Saya memiliki file .csv (di mac) yang memiliki banyak baris kosong, misalnya:
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum
lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum
lorem ipsum ","2","3","4"
Yang ingin saya konversi menjadi:
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
Saya tahu pasti ada satu kalimat tetapi saya tidak tahu awk atau sed. Setiap tips sangat dihargai!
shell
text-processing
sed
awk
pitosalas
sumber
sumber
Jawaban:
Anda dapat menggunakan
-v
mode grep (invert match) untuk melakukan ini:Perhatikan bahwa itu harus file yang berbeda, karena cara kerja pengalihan shell. File output dibuka (dan dikosongkan) sebelum file input dibaca. Jika Anda memiliki lebih banyakutils (tidak secara default pada Mac OS X), Anda dapat menggunakannya
sponge
untuk mengatasi ini:Tapi tentu saja, maka Anda akan lebih sulit untuk kembali jika terjadi kesalahan.
Jika Anda "baris kosong" sebenarnya mungkin berisi spasi (sepertinya memang begitu), maka Anda dapat menggunakan ini sebagai gantinya:
Itu akan mengabaikan garis kosong dan juga baris yang hanya berisi spasi putih. Tentu saja Anda dapat melakukan
sponge
transformasi yang sama .sumber
egrep -v '^[[:space:]]*$'
... perhatikan grep -> egrep dan pola baru yang anehiconv -f utf16le file.csv | head
atauiconv -f utf16be file.csv | head
Opsi termudah adalah adil
grep .
. Di sini, titik berarti "cocokkan apa pun", jadi jika garisnya kosong, itu tidak cocok. Selain itu, ia mencetak seluruh baris apa adanya.sumber
Untuk menghapus garis kosong, di tempat , dengan ksh93:
The
<>;
operator redirection khusus untuk ksh93 dan sama dengan standar<>
Operator kecuali bahwa memotong ksh file setelah perintah telah dihentikan.sed '/./!d'
adalah cara berbelit-belit untuk menulisgrep .
, tetapi sayangnya GNU grep setidaknya mengeluh jika stdout-nya menunjuk ke file yang sama dengan stdin-nya. Anda bisa mengatakan orang bisa menulis:Tapi sayangnya, ada bug di ksh93 (setidaknya versi saya (93u +)), dalam hal file tersebut tampaknya terpotong hingga panjang nol dalam kasus itu.
Tampaknya mengatasi bug itu, tapi sekarang, itu jauh lebih berbelit-belit daripada perintah sed.
sumber
awk '/./' file 1<>; file
yang berhasil. Bagi saya, itu bahkan lebih jelas daripadased '/./!d'
Berikut ini
Perl
satu kalimat untuknya:EDIT: Peningkatan kode berdasarkan komentar ruakh di bawah ini.
sumber
perl -ni -e '/./ and print' yourfile
$
adalah jangkar (yaitu nol-lebar) sehingga tidak termasuk baris baru. Mengenai ruang yang berlebihan, itu alasan saya menambahkan/x
saya tidak inginPerl
mencoba memasukkan `$ \` ke dalam regex$
, mengingat bahwa Anda memiliki\n
. (Atau - Anda tidak perlu\n
, mengingat bahwa Anda memiliki\s*
dan$
; tetapi saya pikirs/^\s*\n//
membuatnya lebih jelas bahwa baris baru dihapus.) Anda juga tidak perlu/m
; itu tidak berpengaruh pada perintah ini. Dan begitu Anda menyingkirkan$
dan ruang, Anda tidak perlu/x
.\n
sendiri dapat dihapus; apa yang tidak dapat Anda lakukan adalah menghapus baik yang$
dan yang\n
. Jadis/^\s*//
akan memiliki masalah yang Anda gambarkan, tetapis/^\s*$//
akan baik-baik saja, karena\s*
dan$
. (Apakah Anda mengerti maksud saya?)$
dapat cocok sebelum baris baru (asalkan/m
bendera diaktifkan, atau baris baru adalah karakter terakhir dari string, atau keduanya), tetapi juga dapat cocok dengan akhir string. Sebagai contoh,"abc" =~ m/^abc$/
itu benar. Dalam kasus\s*$
,\s*
cukup serakah untuk memakan baris baru, dan kemudian$
cocok dengan akhir-string. (Tapi saya pikirs/^\s*\n//
itu lebih jelas, jadi jawaban Anda baik-baik saja seperti sekarang.)Berdasarkan klarifikasi dalam komentar untuk pertanyaan Anda, sesuatu seperti:
dapat melakukan apa yang Anda inginkan.
Pemisah rekaman kosong adalah kasus khusus yang memberi tahu
awk
bahwa catatan harus berupa paragraf (dipisahkan oleh urutan baris kosong). Mengatur pemisah catatan output ke string kosong juga berarti bahwa konten paragraf (tanpa pemisah) harus digabungkan.1
hanyalah kondisi yang benar untuk mencetak setiap catatan.Namun itu akan menghilangkan baris baru, sehingga Anda dapat melakukan:
sumber
Saya tahu ini akan lebih mudah jika saya memberikan file, tetapi sayangnya itu berisi informasi rahasia yang tidak bisa saya bagikan. Sementara itu, saya menulis naskah ruby yang sepertinya berhasil:
Terima kasih semuanya telah membantu!
sumber
menghasilkan
sumber
Saya menemukan ide untuk solusi yang mungkin pada stackoverflow .
sed -i ':a;N;$!ba;s/[^"]\n\s*\n/ /g' file.csv
Anda mungkin harus membuat cadangan file csv Anda sebelum mengujinya, tetapi setidaknya untuk contoh yang Anda berikan itu berfungsi dengan sempurna.
Penjelasan yang baik tentang cara kerja bagian dalam ekspresi ini ditawarkan pada jawabannya, saya hanya mengeditnya untuk mencari baris yang tidak diakhiri dengan a
"
([^"]\n
).sumber
Jika, dari respons Anda sendiri, Anda ingin menghapus karakter baris baru yang terkandung di dalam string yang dikutip, Anda bisa melakukan:
Anda juga bisa menggunakan
-i
flag perl menggunakan untuk mengedit file di tempat .Atau dengan GNU awk:
atau:
(jika Anda bersaing untuk yang terpendek)
Perhatikan bahwa mereka menganggap bahwa tidak ada karakter kutip ganda yang lolos dalam input.
sumber
Sepertinya efeknya yang Anda inginkan lebih dari menghapus baris kosong, tetapi menghapus setiap urutan 2 atau lebih karakter baris baru.
Yang bisa Anda lakukan dengan perl:
Anda juga bisa menggunakan
-i
flag perl menggunakan untuk mengedit file di tempat .sumber
Ada cara yang lebih singkat untuk menghapus garis kosong di
AWK
:awk 'NF' file
Tetapi untuk mendapatkan output yang Anda inginkan, yang dibutuhkan hanyalah satu liner sederhana:
awk 'NF {printf("%s ", $0); i++;} !(i % 2) {printf("\n");}' file
Penjelasan
Dalam
AWK
, baris kosong berarti baris / catatan tidak memiliki bidang, yaituNF
variabel (Jumlah Bidang) adalah nol. Satu liner di atas hanya akan mengeksekusi ketikaNF > 0
, mencetak semua baris, tetapi yang kosong.Ini
i++
adalah penghitung garis yang tidak kosong.Ini
!(i % 2)
digunakan untuk mencetak dua baris non-kosong berturut-turut dengan cara yang Anda inginkan, yaitu, setiap kali kelipatan 2 ditemukan,modulo
pernyataan!(i % 2)
menghasilkan 1, yang mengakhiri rangkaian dua baris non-kosong.sumber
Anda dapat menggunakan Vim dalam mode Ex:
v/./
temukan garis kosongd
menghapusx
Simpan dan tutupsumber