Przefiltruj plik .CSV na podstawie wartości piątej kolumny pliku i wydrukuj te rekordy w nowym pliku

16

Mam plik .CSV w następującym formacie:

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

Piąta kolumna pliku ma różne ciągi. Muszę odfiltrować plik na podstawie wartości 5. kolumny. Powiedzmy, że potrzebuję nowego pliku z bieżącego pliku, który ma rekordy tylko z wartością „string 1” w piątym polu.

W tym celu wypróbowałem poniższe polecenie,

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

ale zgłaszał mi następujący błąd:

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

Następnie użyłem następującego, co daje mi dziwny wynik.

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

Wynik:

"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: Użyłem polecenia toupper, aby być po bezpiecznej stronie, ponieważ nie jestem pewien, czy łańcuch będzie pisany małą, czy większą literą. Muszę wiedzieć, co jest nie tak z moim kodem i czy przestrzeń w ciągu ma znaczenie podczas wyszukiwania wzorca za pomocą AWK.

Dhruuv
źródło

Odpowiedzi:

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

Wynik

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

Myślę, że tego właśnie chcesz.

limovala
źródło
Dane wyjściowe są dokładnie takie, jakie były potrzebne. Nie pomyślałem o tworzeniu '","'jako separatora, inaczej rozwiązałoby to mój problem ... świetne rozwiązanie ...
Dhruuv,
@Dhruuv tworzenie '","'separatora jest tym, co sugeruje większość odpowiedzi na poprzednie pytanie :).
terdon
@terdon: tak, wiem, ale nie przyszło mi to do głowy, gdy miałem problem. Szczerze mówiąc, myślałem, że może to być coś z poleceniem lub coś innego niż ograniczniki, które powodowało problem ... :) Dlatego nie spróbowałem ... :(
Dhruuv
2
@Dhruuv nie jestem pewien szczegółów, ponieważ nie mogę powiedzieć, co próbujesz zrobić, ale twój inny stan jest prawie na pewno zły. Czy próbujesz wydrukować, jeśli 5 USD to HYPERION? Jeśli tak, spróbuj else{if(toupper($5)=="HYPERION"){print}}. Obecnie nie na moim komputerze, więc mogę mieć niepoprawną składnię, ale nie możesz podać warunku dla instrukcji else.
terdon
1
awk -F '","' 'BEGIN {OFS=","} { if (NR==1) {print} else{if (toupper($5) == "STRING 1") print} }' file1
limovala,
2

Problem z CSV polega na tym, że nie ma standardu. Jeśli często masz do czynienia z danymi w formacie CSV, możesz rozważyć bardziej niezawodną metodę, a nie tylko ","separator pól. W tym przypadku Text::CSVmoduły CPAN Perla są wyjątkowo dobrze dostosowane do zadania:

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

źródło
-1
awk 'BEGIN {FS = "," }'  '{ (if toupper($5)  == "STRING 1") print; }'  file1.csv > file2.csv
Zatoka Perska
źródło
Przykro mi to mówić, ale twoje rozwiązanie nie zwraca żadnych zapisów z pliku ... Myślę, że dodanie separatora tak jak '","'to zrobi ... dzięki ... :)
Dhruuv
@Mohsen -1, ponieważ 1) musisz uciec przed "lub nie są one rozumiane jako części ogranicznika pliku. Zobacz odpowiedzi na inne pytanie PO i 2) oddzielasz blok BEGIN od reszty polecenia, co całkowicie łamie go. Spróbuj awk 'BEGIN {FS = "," }' '{print $0}', a zobaczysz, że nie wytwarza żadnych wyników. W przyszłości sprawdź swoje odpowiedzi, aby sprawdzić, czy rzeczywiście działają, zanim je
opublikujesz