Фільтруйте файл .CSV на основі значень файлу у п'ятому стовпці та друкуйте ці записи в новий файл


16

У мене є .CSV файл із форматом нижче:

"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-й стовпець файлу має різні рядки. Мені потрібно відфільтрувати файл на основі значення 5-го стовпця. Скажімо, мені потрібен новий файл із поточного файлу, який має записи лише зі значенням "рядок 1" у п'ятому полі.

Для цього я спробував команду нижче,

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

але це кидало мені помилку наступним чином:

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

Потім я використав наступне, що дає мені непарний вихід.

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

Вихід:

"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: Я використовував команду toupper, щоб бути на безпечній стороні, тому що я не впевнений, чи буде рядок в нижньому чи великому регістрі. Мені потрібно знати, що з моїм кодом не так і якщо пробіл у рядку має значення під час пошуку шаблону за допомогою AWK.

Відповіді:


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

Я думаю, що це те, чого ти хочеш.


Вихід саме такий, як мені це потрібно було. Я не думав робити '","'розмежувач, інакше це вирішило б мою проблему ... чудове рішення ...
Dhruuv

@Dhruuv виготовлення '","'роздільника - це те, що більшість відповідей на попереднє запитання запропоновано :).
тердон

@terdon: так, я знаю, але це мені не спадало на думку, коли у мене виникли проблеми. Чесно кажучи, я подумав, що це може бути щось із командою чи іншим, ніж розмежувачі, що спричинило проблему ... :) Значить, не спробував ... :(
Dhruuv

2
@Dhruuv не впевнений у деталях, оскільки я не можу сказати, що ти намагаєшся зробити, але твій інший стан майже напевно неправильний. Ви намагаєтеся надрукувати оні, якщо 5 доларів - це ГІПЕРІОН? Якщо так, спробуйте else{if(toupper($5)=="HYPERION"){print}}. Наразі не на моєму комп’ютері, тому я, можливо, синтаксис помилився, але ви не можете дати умову іншому твердженню.
terdon

1
awk -F '","' 'BEGIN {OFS=","} { if (NR==1) {print} else{if (toupper($5) == "STRING 1") print} }' file1
лимовала

2

Проблема CSV полягає в тому, що немає стандарту. Якщо вам потрібно часто працювати з даними, відформатованими у форматі CSV, можливо, ви захочете вивчити більш надійний метод, а не просто використовувати його ","як роздільник поля. У цьому випадку Text::CSVмодулі CPAN Perl надзвичайно добре підходять для роботи:

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

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

Вибачте, але ваше рішення не повертає жодних записів з файлу ... Я думаю, що просто додамо роздільник, як '","'це зробить ... дякую ... :)
Dhruuv

@Mohsen -1, тому що 1) вам потрібно уникнути "або вони не розуміються як частини роздільника файлів. Дивіться відповіді на інше питання OP і 2) ви відокремлюєте BEGIN блок від решти команди, яка повністю Спробуйте awk 'BEGIN {FS = "," }' '{print $0}', ви побачите, що це не дає результатів. В майбутньому, будь ласка, протестуйте свої відповіді, щоб побачити, чи справді вони працюють, перш ніж розміщувати їх
terdon
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.