Unix: Birbirini izleyen ardışık düzenler için ardışık virgül bulun ve değiştirin
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
Ş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şirdefined($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
-g
kısaltmasıglobal
(tüm oluşumların yerini alır) vee
Perl'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
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 ,
.
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
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)