Unix: Suchen Sie nach aufeinanderfolgenden Kommas und ersetzen Sie diese durch aufeinanderfolgende Pipelines
Ich konvertiere eine CSV in doppelten Anführungszeichen in eine durch Pipelines getrennte txt-Datei in Unix. Ich habe den folgenden sed-Befehl verwendet, um "," in | zu ersetzen Entfernen Sie dann das doppelte Anführungszeichen am Anfang und am Ende.
sed -e 's/","/|/g' -e 's/"//g' filenm.csv > filenm.txt
Die Datei scheint jedoch aufeinanderfolgende Kommas ohne doppelte Anführungszeichen zu haben und wird nicht ersetzt.
Col1|col2|col3|col4|col5|col6|col7|col8
Val1|val2|val3,,,,val7|val8
Jetzt möchte ich alle diese aufeinanderfolgenden Kommas in aufeinanderfolgende Pipelines konvertieren, da sie leere oder Nullfelder anzeigen.
Andere Felder haben auch Kommas in Feldwerten, die nicht geändert werden sollten.
Ich habe versucht, unten dafür zu verwenden, aber es funktioniert nicht.
sed -e 's/,{1,\}/|{1,\}/g' filenm.csv > filenm.txt
Beispiel-CSV-Datei im Editor geöffnet:
"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"
Ich hoffe, dies hilft, das Problem zu reproduzieren und zu lösen.
Danke im Voraus....
Antworten
Sie können verwenden perl
:
perl -pe 's/"([^"]*)"|,/defined($1) ? $1 : "|"/ge' filenm.csv > filenm.txt
Details :
"([^"]*)"|,
- Das Regex-Muster, das übereinstimmt"
, erfasst dann in Gruppe 1 alle null oder mehr Zeichen außer"
und stimmt dann mit a überein"
oder stimmt,
in allen anderen Kontexten nur mit a übereindefined($1) ? $1 : "|"
- RHS, Ersatz, der die Übereinstimmung entweder durch den Wert der Gruppe 1 (wenn Gruppe 1 übereinstimmte) oder durch einen Wert|
(wenn der,
übereinstimmte) ersetzt.ge
-g
steht fürglobal
(ersetzt alle Vorkommen) unde
lässt Perl die RHS als Perl-Ausdruck behandeln.
Sehen Sie sich einen Online-Test an :
#!/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"
Ausgabe:
ID|Name|DOB|Age|Address|City|State|Country|Phone number
123|ABC|12/20/2020|0|No.38,3rd st, RRR NNN, TRT||||9999999999
Dies könnte für Sie funktionieren (GNU sed):
sed -E ':a;s/^(("[^",]*",+)*"[^",]*),/\1\n/;ta;y/,\n/|,/' file
Ersetzen Sie iterativ ,
's zwischen "
' durch Zeilenumbrüche und übersetzen Sie dann ,
's für |
' s und Zeilenumbrüche für ,
's.
Verwenden von awk:
awk -F \" '{ for(i=1;i<=NF;i++) { if ($i ~ /^[,]{2,}$/) { $i="," } } OFS="\"";gsub("\",\"","\"|\"",$0)}1' sample.csv
Erläuterung:
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
Ich würde GNU AWK
für diesen folgenden Weg verwenden. Lass den file.txt
Inhalt sein
"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"
dann
awk 'BEGIN{FS="\"";OFS=""}{for(i=1;i<=NF;i+=2){$i=gensub(/,/,"|","g",$i)};print $0}' file.txt
Ausgabe
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
Ich nahm an, dass die erste und letzte Spalte niemals leer ist. Ich benutze "
als Feldtrennzeichen und ,
ändere dann in jedem ungeraden Feld (das nur enthält ) alles ,
in |
. Schließlich drucke ich eine ganze solche geänderte Zeile.
(getestet in GNU Awk 5.0.1)