Unix: Birbirini izleyen ardışık düzenler için ardışık virgül bulun ve değiştirin

Jan 08 2021

Unix'te çift tırnaklı bir CSV'yi ardışık düzen sınırlandırılmış txt dosyasına dönüştürüyorum. "," Yerine aşağıdaki sed komutunu kullandım | ardından çift tırnağın başını ve sonunu kaldırın.

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

Ancak dosyada çift tırnaklar olmadan ardışık virgüller var gibi görünüyor ve bunlar değiştirilmiyor.

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

Şimdi tüm bu ardışık virgülleri, boş veya boş alanları gösterdikleri için ardışık ardışık düzenlere dönüştürmek istiyorum.

Ve diğer alanlarda da değiştirilmemesi gereken alan değerleri içinde virgül bulunur.

Bunun için aşağıyı kullanmayı denedim ama çalışmıyor.

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

not defterinde açılan örnek csv dosyası:

"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"

Umarım bu, sorunu yeniden oluşturmaya ve çözmeye yardımcı olur.

Şimdiden teşekkürler....

Yanıtlar

2 WiktorStribiżew Jan 08 2021 at 22:37

Şunları kullanabilirsiniz perl:

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

Detaylar :

  • "([^"]*)"|,- eşleşen normal ifade kalıbı "Grup 1'de herhangi bir sıfır veya daha fazla karakteri yakalar "ve sonra a ile eşleşir "veya ,diğer tüm bağlamlarda sadece a ile eşleşir
  • defined($1) ? $1 : "|"- RHS, (Grup 1 eşleşen ise) Grup 1 değeri ile eşleşen ya da yerine yedek ya da bir ile |(eğer ,eşleşmiş)
  • ge- gkısaltması global(tüm oluşumların yerini alır) ve ePerl'in RHS'yi Perl ifadesi olarak değerlendirmesini sağlar.

Çevrimiçi bir teste bakın :

#!/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"

Çıktı:

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

Bu sizin için işe yarayabilir (GNU sed):

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

,'S arasını "satırsonu ile değiştirin , ardından ,' s for |'s ve ' s için satırsonu çevirin ,.

1 RamanSailopal Jan 09 2021 at 00:35

Awk kullanarak:

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

Açıklama:

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

Bunun için GNU'yu AWKşu şekilde kullanırdım. file.txtİçerik olsun

"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"

sonra

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

çıktı

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

İlk ve son sütunun asla boş olmadığını varsaydım. "Alan ayırıcı olarak kullanıyorum ve sonra her tek alanda (bunlar yalnızca içerir ,) hepsini ,olarak değiştiriyorum |. Sonunda böyle değiştirilmiş bir satır yazdırıyorum.

(GNU Awk 5.0.1'de test edilmiştir)