Saya memiliki file berikut:
id name age
1 ed 50
2 joe 70
Saya ingin mencetak hanya kolom id
dan age
. Saat ini saya hanya menggunakan awk
:
cat file.tsv | awk '{ print $1, $3 }'
Namun, ini membutuhkan mengetahui nomor kolom. Apakah ada cara untuk melakukannya di mana saya dapat menggunakan nama kolom (ditentukan pada baris pertama), alih-alih nomor kolom?
cat
tidak perlu, BTW. Anda bisa menggunakanawk '{ print $1, $3 }' file.tsv
id
bukannya$1
danage
bukannya$3
Jawaban:
Mungkin kira-kira seperti ini:
Jika Anda ingin menentukan kolom yang akan dicetak pada baris perintah, Anda dapat melakukan sesuatu seperti ini:
(Perhatikan
-v
sakelar untuk mendapatkan variabel yang ditentukan dalamBEGIN
blok.)sumber
awk -f t.awk col1 col2 ... coln input
akan menjadi ideal;awk -f t.awk cols=col1,col2,...,coln input
akan bekerja jugafor (i in out)
tidak memiliki urutan bawaan.gawk
menawarkanPROCINFO["sorted_in"]
sebagai solusi, iterasi indeks denganfor( ; ; )
mungkin lebih baik.Hanya dengan memasukkan solusi Perl ke dalam lot:
sumber
csvkit
Konversikan data input ke format csv dan gunakan alat csv seperti
csvcut
daricsvkit
:Instal csvkit:
Gunakan
tr
dengan opsi pemerasannya-s
untuk mengubahnya menjadi file csv yang valid dan menerapkancsvcut
:Jika Anda ingin kembali ke format data lama, Anda dapat menggunakan
tr ',' ' ' | column -t
Catatan
csvkit juga mendukung pembatas yang berbeda ( opsi bersama
-d
atau--delimiter
), tetapi mengembalikan file csv:Jika file hanya menggunakan spasi untuk memisahkan kolom (tidak ada tab sama sekali), berikut ini berfungsi
Jika file menggunakan tab untuk memisahkan kolom, berikut ini berfungsi dan
csvformat
dapat digunakan untuk mendapatkan kembali file tsv:Sejauh yang saya periksa, hanya satu tab yang diizinkan.
csvlook
dapat memformat tabel dalam format tabel penurunan hargaUUOC (Penggunaan Cat yang Tidak Berguna) : Saya suka cara ini untuk membangun perintah.
sumber
tr
juga. File TSV didukung secara langsung, tanpa perlu mengubahnya menjadi CSV. Opsi-t
(alias--tabs
) memberi tahucvscut
untuk menggunakan tab sebagai pembatas bidang. Dan-d
atau--delimiter
menggunakan karakter apa pun sebagai pembatas.-d
dan-t
setengah rusak. mereka bekerja untuk menentukan pembatas input, tetapi pembatas output hardcoded untuk selalu menjadi koma. IMO yang rusak - itu harus sama dengan pembatas input atau memiliki opsi lain untuk memungkinkan pengguna untuk mengatur pembatas output, sepertiawk
FS dan OFS vars.Jika Anda hanya ingin merujuk ke bidang itu dengan nama mereka alih-alih angka, Anda dapat menggunakanread
:EDIT
Akhirnya aku melihat maksudmu! Inilah fungsi bash yang hanya akan mencetak kolom yang Anda tentukan pada baris perintah (berdasarkan nama ).
Inilah cara Anda dapat menggunakannya dengan file yang Anda sajikan:
(Fungsi membaca
stdin
.< file.tsv printColumns ...
Setara denganprintColumns ... < file.tsv
dancat file.tsv | printColumns ...
)Catatan: Perhatikan nama kolom yang Anda minta! Versi ini tidak memiliki pemeriksaan kewarasan, sehingga hal-hal buruk dapat terjadi jika salah satu argumennya seperti
"anything; rm /my/precious/file"
sumber
id
,name
danage
, tidak mengubah fakta bahwa pesanan tersebut dikodekan dengan keras diread
baris Anda .time { command(s); }
).time cat temp.txt | ./col1 CHR POS > /dev/null 99.144u 38.966s 2:19.27 99.1% 0+0k 0+0io 0pf+0w time awk -f col2 c1=CHR c2=POS temp.txt > /dev/null 0.294u 0.127s 0:00.50 82.0% 0+0k 0+0io 0pf+0w
Untuk apa nilainya. Ini dapat menangani sejumlah kolom di sumber, dan sejumlah kolom untuk dicetak, dalam urutan output apa pun yang Anda pilih; hanya mengatur ulang args ...
misalnya. panggilan:
script-name id age
keluaran
sumber
Jika file yang Anda baca tidak pernah mungkin dibuat oleh pengguna, Anda dapat menyalahgunakan yang sudah dibaca:
Seluruh baris pertama file input diganti ke dalam daftar argumen, jadi
read
diteruskan semua nama bidang dari baris header sebagai nama variabel. Yang pertama akan diberi 1 yangseq 100
menghasilkan, yang kedua mendapat 2, yang ketiga mendapat 3 dan seterusnya. Kelebihanseq
output direndam oleh variabel dummyextra
. Jika Anda mengetahui jumlah kolom input sebelumnya, Anda dapat mengubah 100 untuk mencocokkan dan menghilangkanextra
.The
awk
Script adalah string dikutip ganda, memungkinkan variabel shell didefinisikan olehread
harus diganti ke dalam naskah sebagaiawk
nomor lapangan.sumber
Biasanya lebih mudah hanya dengan melihat file header, menghitung jumlah kolom yang Anda butuhkan ( c ) dan kemudian menggunakan Unix
cut
:Tetapi ketika ada banyak kolom atau banyak file saya menggunakan trik jelek berikut:
Diuji pada OSX,
file.csv
koma-delimted.sumber
Inilah satu cara cepat untuk memilih satu kolom.
Katakanlah kita ingin kolom bernama "foo":
Pada dasarnya, ambil baris tajuk, bagi menjadi beberapa baris dengan satu nama kolom per baris, beri nomor pada baris, pilih baris dengan nama yang diinginkan, dan ambil nomor baris yang terkait; kemudian gunakan nomor baris itu sebagai nomor kolom ke perintah cut.
sumber
Mencari solusi yang sama (saya perlu kolom bernama id, yang mungkin memiliki nomor kolom yang bervariasi), saya menemukan yang ini:
sumber
Saya menulis skrip Python untuk tujuan ini yang pada dasarnya berfungsi seperti ini:
Saya menyebutnya
hgrep
untuk sundulan grep , dapat digunakan seperti ini:Keseluruhan skrip sedikit lebih lama, karena digunakan
argparse
untuk menguraikan argumen baris perintah dan kode adalah sebagai berikut:sumber
awk
, untuk semua vintage-nya, secara inheren diindeks integer, sebagaimana adanyacut
.Berikut adalah beberapa alat yang dirancang untuk menangani data berindeks nama (kebanyakan dari mereka hanya menangani CSV dan TSV, yang merupakan format file yang sangat populer):
sumber
Coba utilitas awk kecil ini untuk memotong header tertentu - https://github.com/rohitprajapati/toyeca-cutter
Contoh penggunaan -
sumber