it-swarm-id.com

Ekstrak kolom tertentu dari file terbatas menggunakan Awk

Maaf jika ini terlalu mendasar. Saya memiliki file csv di mana kolom memiliki baris tajuk (v1, v2, dll.). Saya mengerti bahwa untuk mengekstrak kolom 1 dan 2, saya harus lakukan: awk -F "," '{print $1 "," $2}' infile.csv > outfile.csv. Tetapi bagaimana jika saya harus mengekstraksi, katakanlah, kolom 1 sampai 10, 20 hingga 25, dan 30, 33? Sebagai tambahan, apakah ada cara untuk mengekstrak langsung dengan nama header daripada dengan nomor kolom?

32
user702432

Saya tidak tahu apakah mungkin melakukan rentang awk. Anda dapat melakukan for for, tetapi Anda harus menambahkan penanganan untuk menyaring kolom yang tidak Anda inginkan. Mungkin lebih mudah untuk melakukan ini:

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

sesuatu yang lain untuk dipertimbangkan - dan ini lebih cepat dan lebih ringkas:

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

Adapun bagian kedua dari pertanyaan Anda, saya mungkin akan menulis skrip di Perl yang tahu bagaimana menangani baris header, mem-parsing nama kolom dari stdin atau file dan kemudian melakukan penyaringan. Mungkin alat yang saya ingin miliki untuk hal-hal lain. Saya tidak yakin melakukan dalam satu liner, meskipun saya yakin itu bisa dilakukan.

51
Cliff

Seperti yang disebutkan oleh @Tom, pendekatan cut and awk sebenarnya tidak berfungsi untuk CSV dengan string yang dikutip. Alternatif adalah modul untuk python yang menyediakan alat baris perintah csvfilter. Ini berfungsi seperti cut, tetapi menangani kolom CSV dengan tepat:

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

Jika Anda memiliki python (dan seharusnya), Anda dapat menginstalnya seperti ini:

pip install csvfilter

Harap perhatikan bahwa pengindeksan kolom di csvfilter dimulai dengan 0 (tidak seperti awk, yang dimulai dengan $ 1). Info lebih lanjut di https://github.com/codeinthehole/csvfilter/

11
studgeek

Orang lain telah menjawab pertanyaan Anda sebelumnya. Untuk ini:

Sebagai tambahan, apakah ada cara untuk mengekstrak langsung dengan nama header daripada dengan nomor kolom?

Saya belum mencobanya, tetapi Anda bisa menyimpan indeks masing-masing header dalam hash dan kemudian menggunakan hash itu untuk mendapatkan indeksnya nanti.

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

Kemudian, gunakan:

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

Bahasa lain memiliki jalan pintas untuk rentang nomor bidang, tetapi tidak awk, Anda harus menulis kode Anda sebagai ketakutan Anda ;-)

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

Tidak ada fungsi langsung dalam awk untuk menggunakan nama bidang sebagai penentu kolom.

Saya harap ini membantu.

3
shellter

Anda dapat menggunakan for-loop untuk mengatasi bidang dengan $ i :

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

Tabulator adalah seperangkat alat baris perintah unix untuk bekerja dengan file csv yang memiliki baris header. Berikut adalah contoh untuk mengekstrak kolom berdasarkan nama dari file 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

Kemudian tblmap -k name,height test.csv menghasilkan

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

Jika Perl adalah opsi:

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 baris autosplits ke dalam array bidang @F. Indeks mulai dari 0 (bukan 1 seperti awk)
pemisah bidang -F, adalah,

Jika file CSV Anda mengandung koma dalam tanda kutip, parser CSV yang lengkap seperti Text::CSV_XS Perl dibuat khusus untuk menangani keanehan semacam itu. 

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])}'

Saya memberikan penjelasan lebih lanjut dalam jawaban saya di sini: file csv parse menggunakan gawk

0
Chris Koknat

Tidak menggunakan awk tetapi cara paling sederhana yang bisa saya lakukan adalah dengan menggunakan csvtool . Saya punya kasus penggunaan lain juga untuk menggunakan csvtool dan dapat menangani tanda kutip atau pembatas dengan tepat jika mereka muncul dalam kolom data itu sendiri.

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

Mengganti 2 dengan nomor kolom akan secara efektif mengekstrak data kolom yang Anda cari.

0
Samar