Saya memiliki file csv besar dengan 10 bidang yang dipisahkan oleh koma. Sayangnya, beberapa baris salah format dan tidak mengandung tepat 10 koma (apa yang menyebabkan beberapa masalah ketika saya ingin membaca file menjadi R). Bagaimana saya bisa memfilter hanya garis yang berisi tepat 10 koma?
9
sed
ada di sini) hanya sejauh satu kecocokan lebih dari yang dicari, meskipun pertanyaan ini. Anda seharusnya tidak menutup ini.grep
jawabannya tidak ada jawaban yang dapat diterima untuk kedua pertanyaan ...Jawaban:
Satu lagi POSIX:
Jika garis memiliki 10 koma, maka akan ada 11 bidang di baris ini. Jadi kita cukup
awk
gunakan,
sebagai pembatas bidang. Jika jumlah bidang adalah 11, kondisinyaNF == 11
benar,awk
kemudian lakukan tindakan defaultprint $0
.sumber
-F
set pemisah bidang danNF
merujuk ke jumlah bidang dalam baris yang diberikan. Karena tidak ada blok kode{statement}
yang ditambahkan ke kondisiNF == 11
, tindakan standar adalah mencetak baris. (@cuonglm, jangan ragu untuk memasukkan penjelasan ini jika Anda suka.)awk -F , 'NF != 11' <file
-
atau bernama-
.Menggunakan
egrep
(ataugrep -E
dalam POSIX):Ini menyaring apa pun yang tidak mengandung 10 koma: cocok dengan garis penuh (
^
di awal dan$
di akhir), yang mengandung tepat sepuluh pengulangan ({10}
) dari urutan "sejumlah karakter kecuali ',', diikuti oleh satu ','" (([^,]*,)
), diikuti lagi oleh sejumlah karakter kecuali ',' ([^,]*
).Anda juga dapat menggunakan
-x
parameter untuk menjatuhkan jangkar:Ini kurang efisien daripada cuonglm 's
awk
solusi meskipun; yang terakhir biasanya enam kali lebih cepat pada sistem saya untuk jalur dengan sekitar 10 koma. Garis yang lebih panjang akan menyebabkan perlambatan besar.sumber
grep
Kode paling sederhana yang akan berfungsi:Penjelasan:
-x
memastikan bahwa polanya harus cocok dengan seluruh garis, bukan hanya sebagian saja. Ini penting agar Anda tidak mencocokkan garis dengan lebih dari 10 koma.-E
berarti "regex diperpanjang", yang membuat lebih sedikit garis miring terbalik di regex Anda.Tanda kurung digunakan untuk pengelompokan, dan
{10}
setelah itu berarti harus ada tepat sepuluh pertandingan dalam satu baris pola di dalam tanda kurung.[^,]
adalah kelas karakter — misalnya,[c-f]
akan cocok dengan karakter tunggal apa pun yang ac
, ad
, ae
atau af
, dan[^A-Z]
akan cocok dengan karakter tunggal apa pun yang BUKAN huruf besar. Jadi[^,]
cocok dengan setiap karakter kecuali koma.The
*
setelah sarana kelas karakter "nol atau lebih dari ini."Jadi bagian regex
([^,]*,)
berarti "Karakter apa pun kecuali koma beberapa kali (termasuk nol kali), diikuti oleh koma" dan{10}
menentukan 10 di antaranya. Kemudian[^,]*
untuk mencocokkan sisa karakter non-koma ke akhir baris.sumber
Yang pertama bercabang garis apa pun dengan 11 atau lebih koma, dan kemudian mencetak yang tersisa hanya mereka yang cocok dengan 10 koma.
Rupanya saya menjawab ini sebelumnya ... Ini adalah saya-plagiarisme dari pertanyaan mencari persis 4 kejadian dari beberapa pola:
sumber
s/hello/world/2
dengans//world/2
, GNU sed berfungsi dengan baik. Dengan duased
dari pusaka,/usr/5bin/posix/sed
angkat segfault,/usr/5bin/sed
masuk ke loop infinitif.sed
danawk
(dalam komentar) —Saya menyukai jawaban ini dan memutakhirkannya, tetapi perhatikan terjemahan dariawk
jawaban yang diterima adalah: "Cetak baris dengan 11 bidang" dan terjemahan darised
jawaban ini adalah: " Cobalah untuk menghapus koma ke-11; lompati ke baris berikutnya jika Anda gagal. Cobalah untuk mengganti koma ke-10 dengan dirinya; cetak baris jika Anda berhasil. " Theawk
jawabannya memberikan petunjuk untuk komputer seperti yang Anda akan mengungkapkannya dalam bahasa Inggris. (awk
baik untuk data berbasis lapangan.)Membuang beberapa pendek
python
:Ini akan membaca setiap baris dan memeriksa apakah jumlah koma di baris sama dengan 10
line.count(',') == 10
, jika demikian cetak maka akan menjadi baris.sumber
Dan inilah cara Perl:
The
-n
menyebabkanperl
untuk membaca file baris input dengan baris dan mengeksekusi script yang diberikan oleh-e
pada setiap baris. The-a
bergantian pada membelah otomatis: setiap baris masukan akan dibagi pada nilai yang diberikan oleh-F
(di sini, koma) dan disimpan sebagai array@F
.The
$#F
(atau, lebih umum$#array
), adalah indeks tertinggi dari array@F
. Sejak array mulai0
, garis dengan 11 bidang akan memiliki@F
dari10
. Script, oleh karena itu, mencetak baris jika memiliki 11 bidang.sumber
print if @F==11
sebagai array dalam konteks skalar mengembalikan jumlah elemen.Jika bidang dapat berisi koma atau baris baru, kode Anda perlu memahami csv. Contoh (dengan tiga kolom):
Saya kira sebagian besar solusi sejauh ini akan membuang baris kedua dan keempat.
sumber