Unix: Temukan dan ganti koma yang berurutan ke pipeline yang berurutan

Jan 08 2021

Saya mengonversi CSV yang dikutip ganda menjadi file txt yang dibatasi pipa di Unix. Saya telah menggunakan perintah sed berikut untuk mengganti "," menjadi | lalu hapus tanda kutip ganda awal dan akhir.

sed -e 's/","/|/g' -e 's/"//g' filenm.csv > filenm.txt

Namun file tersebut tampaknya memiliki koma yang berurutan tanpa tanda kutip ganda dan tidak diganti.

Col1|col2|col3|col4|col5|col6|col7|col8
Val1|val2|val3,,,,val7|val8

Sekarang saya ingin mengubah semua koma yang berurutan ini menjadi pipeline yang berurutan karena menunjukkan bidang kosong atau nol.

Dan bidang lain juga memiliki koma di dalam nilai bidang yang tidak boleh diubah.

Saya mencoba menggunakan di bawah ini untuk itu, tetapi tidak berhasil.

sed -e 's/,{1,\}/|{1,\}/g' filenm.csv > filenm.txt

contoh file csv dibuka di notepad:

"ID","Name","DOB","Age","Address","City","State","Country","Phone number"
"123","ABC","12/20/2020","15","No.38,3rd st, RRR NNN, TRT",,,,"9999999999"
"456","DEF","12/20/2020",,,,,"test-country","9999999999"
"465","XYZ",,,"No.38,3rd st, RRR NNN, TRT",,,,"9999999999"

Saya harap ini membantu mereproduksi masalah dan menyelesaikannya.

Terima kasih sebelumnya....

Jawaban

2 WiktorStribiżew Jan 08 2021 at 22:37

Anda dapat menggunakan perl:

perl -pe 's/"([^"]*)"|,/defined($1) ? $1 : "|"/ge' filenm.csv > filenm.txt

Detailnya :

  • "([^"]*)"|,- pola regex yang cocok ", lalu menangkap ke dalam Grup 1 karakter apa pun yang tidak ada atau lebih selain "dan kemudian cocok dengan a ", atau hanya cocok dengan a ,di semua konteks lainnya
  • defined($1) ? $1 : "|"- Kanan, pengganti, yang menggantikan pertandingan baik dengan nilai Grup 1 (jika Grup 1 cocok) atau dengan |(jika ,cocok)
  • ge- gsingkatan global(menggantikan semua kejadian) dan emembuat Perl memperlakukan RHS sebagai ekspresi Perl.

Lihat tes online :

#!/bin/bash
s='"ID","Name","DOB","Age","Address","City","State","Country","Phone number"
"123","ABC","12/20/2020","0","No.38,3rd st, RRR NNN, TRT",,,,"9999999999"'
perl -pe 's/"([^"]*)"|,/defined($1) ? $1 : "|"/ge' <<< "$s"

Keluaran:

ID|Name|DOB|Age|Address|City|State|Country|Phone number
123|ABC|12/20/2020|0|No.38,3rd st, RRR NNN, TRT||||9999999999
4 potong Jan 08 2021 at 23:05

Ini mungkin berhasil untuk Anda (GNU sed):

sed -E ':a;s/^(("[^",]*",+)*"[^",]*),/\1\n/;ta;y/,\n/|,/' file

Ganti baris ,antara "dengan baris baru, lalu terjemahkan ,untuk |baris dan baris baru untuk ,.

1 RamanSailopal Jan 09 2021 at 00:35

Menggunakan awk:

awk -F \" '{ for(i=1;i<=NF;i++) { if ($i ~ /^[,]{2,}$/) { $i="," } } OFS="\"";gsub("\",\"","\"|\"",$0)}1' sample.csv

Penjelasan:

awk -F \" '{  # Set the field delimiter to double quote
             for(i=1;i<=NF;i++) { 
               if ($i ~ /^[,]{2,}$/) { 
                  $i="," # Loop through each field and if is contains 2 or more commas, set that field to one comma } } OFS="\""; gsub("\",\"","\"|\"",$0) # Substitute "," for "|"
           }1' sample.csv
1 Daweo Jan 09 2021 at 01:50

Saya akan menggunakan GNU AWKuntuk cara berikut ini. Biarkan file.txtkonten menjadi

"ID","Name","DOB","Age","Address","City","State","Country","Phone number"
"123","ABC","12/20/2020","15","No.38,3rd st, RRR NNN, TRT",,,,"9999999999"
"456","DEF","12/20/2020",,,,,"test-country","9999999999"
"465","XYZ",,,"No.38,3rd st, RRR NNN, TRT",,,,"9999999999"

kemudian

awk 'BEGIN{FS="\"";OFS=""}{for(i=1;i<=NF;i+=2){$i=gensub(/,/,"|","g",$i)};print $0}' file.txt

keluaran

ID|Name|DOB|Age|Address|City|State|Country|Phone number
123|ABC|12/20/2020|15|No.38,3rd st, RRR NNN, TRT||||9999999999
456|DEF|12/20/2020|||||test-country|9999999999
465|XYZ|||No.38,3rd st, RRR NNN, TRT||||9999999999

Saya berasumsi bahwa kolom pertama dan terakhir tidak pernah kosong. Saya gunakan "sebagai pemisah bidang dan kemudian di setiap bidang ganjil (ini hanya berisi ,) saya mengubah semua ,menjadi |. Akhirnya saya mencetak seluruh baris yang diubah tersebut.

(diuji di GNU Awk 5.0.1)