Lọc tệp .CSV dựa trên các giá trị cột thứ 5 của tệp và in các bản ghi đó thành tệp mới


16

Tôi có tệp .CSV với định dạng dưới đây:

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

Cột thứ 5 của tệp có các chuỗi khác nhau. Tôi cần lọc ra tệp dựa trên giá trị cột thứ 5. Hãy nói rằng, tôi cần một tệp mới từ tệp hiện tại chỉ có các bản ghi với giá trị "chuỗi 1" trong trường thứ năm của nó.

Đối với điều này, tôi đã thử lệnh dưới đây,

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

nhưng nó đã ném cho tôi một lỗi như sau:

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

Sau đó tôi đã sử dụng sau đây cho tôi một đầu ra lẻ.

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

Đầu ra:

"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: Tôi đã sử dụng lệnh toupper để ở bên an toàn, vì tôi không chắc chuỗi sẽ ở dạng thấp hơn hay cao hơn. Tôi cần phải biết những gì sai với mã của tôi và nếu không gian trong chuỗi có vấn đề trong khi tìm kiếm một mẫu bằng AWK.

Câu trả lời:


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

Đầu ra

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

Tôi nghĩ rằng đây là những gì bạn muốn.


Đầu ra chính xác là tôi cần nó như thế nào. Tôi đã không nghĩ đến việc '","'làm dấu phân cách, nếu không nó sẽ giải quyết được vấn đề của tôi ... giải pháp tuyệt vời ...
Dhruuv

@Dhruuv làm cho '","'dấu phân cách là những gì hầu hết câu trả lời cho câu hỏi trước đây của bạn đề xuất :).
terdon

@terdon: vâng, tôi biết, nhưng điều đó không đi vào tâm trí của tôi khi tôi gặp vấn đề. Thành thật mà nói, tôi nghĩ rằng nó có thể là một cái gì đó với lệnh hoặc một cái gì đó khác với các dấu phân cách gây ra vấn đề ... :) Do đó đã không thử ... :(
Dhruuv

2
@Dhruuv không chắc chắn về các chi tiết vì tôi không thể nói bạn đang cố gắng làm gì nhưng điều kiện khác của bạn gần như chắc chắn là sai. Bạn đang cố gắng in ony nếu $ 5 là HY SINH? Nếu vậy, hãy thử else{if(toupper($5)=="HYPERION"){print}}. Không phải tại máy tính của tôi vào lúc này vì vậy tôi có thể sai cú pháp nhưng bạn không thể đưa ra một điều kiện cho một câu lệnh khác.
terdon

1
awk -F '","' 'BEGIN {OFS=","} { if (NR==1) {print} else{if (toupper($5) == "STRING 1") print} }' file1
limovala

2

Vấn đề với CSV là không có tiêu chuẩn. Nếu bạn cần thường xuyên xử lý dữ liệu có định dạng CSV, bạn có thể muốn xem xét một phương pháp mạnh mẽ hơn thay vì chỉ sử dụng ","làm dấu tách trường. Trong trường hợp này, Text::CSVcác mô-đun CPAN của Perl đặc biệt phù hợp với công việc:

$ 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

Rất tiếc phải nói, nhưng giải pháp của bạn không trả lại bất kỳ hồ sơ nào từ tệp ... Tôi nghĩ chỉ cần thêm dấu phân cách như '","'sẽ làm ... cảm ơn ... :)
Dhruuv

@Mohsen -1 vì 1) bạn cần thoát "hoặc chúng không được hiểu là một phần của dấu phân cách tệp. Xem câu trả lời cho câu hỏi khác của OP và 2) bạn đang tách khối BEGIN khỏi phần còn lại của lệnh. Hãy thử xem awk 'BEGIN {FS = "," }' '{print $0}', bạn sẽ thấy nó không tạo ra kết quả. Trong tương lai, vui lòng kiểm tra câu trả lời của bạn để xem chúng có thực sự hoạt động hay không trước khi đăng chúng.
terdon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.