it-swarm-vi.tech

Trích xuất các cột cụ thể từ tệp được phân tách bằng Awk

Xin lỗi nếu điều này là quá cơ bản. Tôi có một tệp csv trong đó các cột có một hàng tiêu đề (v1, v2, v.v.). Tôi hiểu rằng để trích xuất cột 1 và 2, tôi phải làm: awk -F "," '{print $1 "," $2}' infile.csv > outfile.csv. Nhưng nếu tôi phải trích xuất, giả sử, các cột từ 1 đến 10, 20 đến 25 và 30, 33 thì sao? Là một phụ lục, có cách nào để trích xuất trực tiếp bằng tên tiêu đề thay vì bằng số cột không?

32
user702432

Tôi không biết nếu có thể thực hiện phạm vi trong awk. Bạn có thể thực hiện một vòng lặp for, nhưng bạn sẽ phải thêm xử lý để lọc ra các cột bạn không muốn. Có lẽ dễ dàng hơn để làm điều này:

awk -F, '{OFS=",";print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$20,$21,$22,$23,$24,$25,$30,$33}' infile.csv > outfile.csv

một cái gì đó khác để xem xét - và điều này nhanh hơn và ngắn gọn hơn:

cut -d "," -f1-10,20-25,30-33 infile.csv > outfile.csv

Đối với phần thứ hai của câu hỏi của bạn, tôi có thể sẽ viết một tập lệnh trong Perl, biết cách xử lý các hàng tiêu đề, phân tích tên cột từ stdin hoặc một tệp và sau đó thực hiện lọc. Nó có lẽ là một công cụ tôi muốn có cho những thứ khác. Tôi không chắc chắn về việc thực hiện trong một lớp lót, mặc dù tôi chắc chắn rằng nó có thể được thực hiện.

51
Cliff

Như được đề cập bởi @Tom, các cách tiếp cận cắt và awk thực sự không hoạt động đối với CSV với các chuỗi được trích dẫn. Một thay thế là một mô-đun cho python cung cấp công cụ dòng lệnh csvfilter. Nó hoạt động như cắt, nhưng xử lý đúng cách trích dẫn cột CSV:

csvfilter -f 1,3,5 in.csv > out.csv

Nếu bạn có python (và bạn nên), bạn có thể cài đặt nó đơn giản như thế này:

pip install csvfilter

Xin lưu ý rằng việc lập chỉ mục cột trong csvfilter bắt đầu bằng 0 (không giống như awk, bắt đầu bằng $ 1). Thêm thông tin tại https://github.com/codeinthehole/csvfilter/

11
studgeek

Những người khác đã trả lời câu hỏi trước đó của bạn. Đối với điều này:

Là một phụ lục, có cách nào để trích xuất trực tiếp bằng tên tiêu đề thay vì bằng số cột không?

Tôi chưa thử nó, nhưng bạn có thể lưu trữ chỉ mục của từng người trong một hàm băm và sau đó sử dụng hàm băm đó để lấy chỉ mục sau này.

for(i=0;i<$NF;i++){
    hash[$i] = i;
}

Sau đó, sử dụng nó:

j = hash["header1"];
print $j;
3
Ritesh

Các ngôn ngữ khác có các đường cắt ngắn cho phạm vi số trường, nhưng không phải là awk, bạn sẽ phải viết mã vì sợ hãi ;-)

awk -F, 'BEGIN {OFS=","} { print $1, $2, $3, $4 ..... $30, $33}' infile.csv > outfile.csv

Không có chức năng trực tiếp trong awk để sử dụng tên trường làm chỉ định cột.

Tôi hi vọng cái này giúp được.

3
shellter

Bạn có thể sử dụng vòng lặp for để giải quyết một trường có $ i :

ls -l | awk '{for(i=3 ; i<8 ; i++) {printf("%s\t", $i)} print ""}'
2
Raymond Hettinger

Tabulator là một tập hợp các công cụ dòng lệnh unix để làm việc với các tệp csv có dòng tiêu đề. Dưới đây là một ví dụ để trích xuất các cột theo tên từ tệp test.csv:

name,sex,house_nr,height,shoe_size
arthur,m,42,181,11.5
berta,f,101,163,8.5
chris,m,1333,175,10
don,m,77,185,12.5
elisa,f,204,166,7

Sau đó, tblmap -k name,height test.csv tạo ra

name,height
arthur,181
berta,163
chris,175
don,185
elisa,166
1
stefan.schroedl

Nếu Perl là một tùy chọn:

Perl -F, -lane 'print join ",",@F[0,1,2,3,4,5,6,7,8,9,19,20,21,22,23,24,29,32]'

-a autosplits dòng vào @F mảng trường. Các chỉ số bắt đầu từ 0 (không phải 1 như trong awk)
[.__.] -F, dấu phân cách trường là,

Nếu tệp CSV của bạn chứa dấu phẩy trong dấu ngoặc kép, các trình phân tích cú pháp CSV hoàn chỉnh như Perl's Text::CSV_XS được xây dựng có mục đích để xử lý loại kỳ lạ đó.

Perl -MText::CSV_XS -lne 'BEGIN{$csv=Text::CSV_XS->new()} if($csv->parse($_)){@f=$csv->fields();print (join ",",@f[0,1,2,3,4,5,6,7,8,9,19,20,21,22,23,24,29,32])}'

Tôi đã cung cấp thêm lời giải thích trong câu trả lời của mình ở đây: phân tích tệp csv bằng gawk

0
Chris Koknat

Không sử dụng awk nhưng cách đơn giản nhất tôi có thể thực hiện được là chỉ sử dụng csvtool . Tôi cũng có các trường hợp sử dụng khác để sử dụng csvtool và nó có thể xử lý các trích dẫn hoặc dấu phân cách một cách thích hợp nếu chúng xuất hiện trong chính dữ liệu cột.

csvtool format '%(2)\n' input.csv
csvtool format '%(2),%(3),%(4)\n' input.csv

Thay thế 2 bằng số cột sẽ trích xuất hiệu quả dữ liệu cột bạn đang tìm kiếm.

0
Samar