Filtern Sie eine CSV-Datei basierend auf den Werten der fünften Spalte einer Datei und drucken Sie diese Datensätze in eine neue Datei

16

Ich habe eine CSV-Datei mit dem folgenden Format:

"column 1","column 2","column 3","column 4","column 5","column 6","column 7","column 8","column 9","column 10
"12310","42324564756","a simple string with a , comma","string with or, without commas","string 1","USD","12","70%","08/01/2013",""
"23455","12312255564","string, with, multiple, commas","string with or, without commas","string 2","USD","433","70%","07/15/2013",""
"23525","74535243123","string , with commas, and - hypens and: semicolans","string with or, without commas","string 1","CAND","744","70%","05/06/2013",""
"46476","15467534544","lengthy string, with commas, multiple: colans","string with or, without commas","string 2","CAND","388","70%","09/21/2013",""

5. Spalte der Datei hat verschiedene Zeichenfolgen. Ich muss die Datei basierend auf dem Wert der 5. Spalte herausfiltern. Nehmen wir an, ich benötige eine neue Datei aus der aktuellen Datei, die nur Datensätze mit dem Wert "string 1" im fünften Feld enthält.

Dazu habe ich den folgenden Befehl ausprobiert:

awk -F"," ' { if toupper($5) == "STRING 1") PRINT }' file1.csv > file2.csv

aber es warf mir einen Fehler wie folgt:

awk: { if toupper($5) == "STRING 1") PRINT }
awk: ^ syntax error
awk: { if toupper($5) == "STRING 1") PRINT }
awk: ^ syntax error

Ich habe dann die folgenden verwendet, die mir eine ungerade Ausgabe gibt.

awk -F"," '$5="string 1" {print}' file1.csv > file2.csv

Ausgabe:

"column 1" "column 2" "column 3" "column 4" string 1 "column 6" "column 7" "column 8" "column 9" "column 10
"12310" "42324564756" "a simple string with a comma" string 1 without commas" "string 1" "USD" "12" "70%" "08/01/2013" ""
"23455" "12312255564" "string with string 1 commas" "string with or without commas" "string 2" "USD" "433" "70%" "07/15/2013" ""
"23525" "74535243123" "string with commas string 1 "string with or without commas" "string 1" "CAND" "744" "70%" "05/06/2013" ""
"46476" "15467534544" "lengthy string with commas string 1 "string with or without commas" "string 2" "CAND" "388" "70%" "09/21/2013" ""

PS: Ich habe den Befehl toupper verwendet, um auf der sicheren Seite zu sein, da ich nicht sicher bin, ob die Zeichenfolge in Groß- oder Kleinschreibung geschrieben wird. Ich muss wissen, was mit meinem Code nicht stimmt und ob das Leerzeichen in der Zeichenfolge wichtig ist, wenn ich mit AWK nach einem Muster suche.

Dhruuv
quelle

Antworten:

17
awk -F '","'  'BEGIN {OFS=","} { if (toupper($5) == "STRING 1")  print }' file1.csv > file2.csv 

Ausgabe

"12310","42324564756","a simple string with a , comma","string with or, without commas","string 1","USD","12","70%","08/01/2013",""
"23525","74535243123","string , with commas, and - hypens and: semicolans","string with or, without commas","string 1","CAND","744","70%","05/06/2013",""

Ich denke das ist was du willst.

limovala
quelle
Die Ausgabe ist genau so, wie ich es brauchte. Ich habe nicht gedacht, '","'als Trennzeichen zu machen, sonst hätte es mein Problem gelöst ... großartige Lösung ...
Dhruuv
@ Thruuv machen '","'das Trennzeichen ist, was die meisten Antworten auf Ihre vorherige Frage vorgeschlagen :).
Terdon
@terdon: ja, ich weiß, aber das kam mir nicht in den Sinn, als ich das Problem hatte. Ehrlich gesagt dachte ich, es könnte etwas mit dem Befehl oder etwas anderem als den Begrenzern sein, das das Problem verursacht hat ... :) Also habe ich es nicht ausprobiert ... :(
Dhruuv 22.10.13
2
@ Thruuv nicht sicher über die Details, da ich nicht sagen kann, was Sie versuchen zu tun, aber Ihr sonst Zustand ist fast sicher falsch. Versuchen Sie, nur zu drucken, wenn 5 US-Dollar HYPERION sind? Wenn ja, versuche es else{if(toupper($5)=="HYPERION"){print}}. Momentan nicht auf meinem Computer, daher habe ich möglicherweise die falsche Syntax, aber Sie können einer else-Anweisung keine Bedingung zuweisen.
Terdon
1
awk -F '","' 'BEGIN {OFS=","} { if (NR==1) {print} else{if (toupper($5) == "STRING 1") print} }' file1
Limovala
2

Das Problem mit CSV ist, dass es keinen Standard gibt. Wenn Sie häufig mit CSV-formatierten Daten arbeiten müssen, sollten Sie eine robustere Methode ausprobieren, anstatt sie nur ","als Feldtrennzeichen zu verwenden. In diesem Fall Text::CSVeignen sich die CPAN-Module von Perl hervorragend für diese Aufgabe:

$ perl -mText::CSV_XS -WlanE '
    BEGIN {our $csv = Text::CSV_XS->new;} 
    $csv->parse($_); 
    my @fields = $csv->fields(); 
    print if $fields[4] =~ /string 1/i;
' file1.csv
"12310","42324564756","a simple string with a , comma","string with or, without commas","string 1","USD","12","70%","08/01/2013",""
"23525","74535243123","string , with commas, and - hypens and: semicolans","string with or, without commas","string 1","CAND","744","70%","05/06/2013",""

quelle
-1
awk 'BEGIN {FS = "," }'  '{ (if toupper($5)  == "STRING 1") print; }'  file1.csv > file2.csv
Persischer Golf
quelle
Tut mir leid zu sagen, aber Ihre Lösung gibt keine Datensätze aus der Datei zurück ... Ich denke, nur das Trennzeichen hinzuzufügen, wie es '","'geht ... danke ... :)
Dhruuv
@Mohsen -1 weil 1) Sie müssen das "oder sie werden nicht als Teile des Dateibegrenzers verstanden. Siehe die Antworten auf die andere Frage des OP und 2) Sie trennen den BEGIN-Block vom Rest des Befehls, der vollständig Versuchen Sie awk 'BEGIN {FS = "," }' '{print $0}', Sie werden sehen, dass es keine Ausgabe erzeugt. Testen Sie in Zukunft Ihre Antworten, um zu sehen, ob sie tatsächlich funktionieren, bevor Sie sie veröffentlichen.
terdon