Cara memotong kolom kedua hingga panjang yang diberikan


9

Diberikan input dari formulir

XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar foolkasjfdrte

bagaimana saya bisa memotong kolom kedua saja? Pembatasnya adalah TAB dan kolom kedua harus paling panjang 75 karakter.


Agak lebih umum:awk 'BEGIN{OFS=FS="\t"} {$2=substr($2,1,75)}1' file
fedorqui

Apakah Anda ingin memotong (menghapus karakter setelah ke-75) atau melipat (mencetaknya di baris lain)? Juga, haruskah spasi dihitung ke 75 karakter atau tidak?
terdon

Jawaban:


7

Jika Anda ingin mencetak hanya 75 karakter pertama dari kolom kedua (termasuk spasi, dan dengan asumsi hanya dua kolom dalam file), Anda dapat melakukan:

$ perl -pe 's/(\t.{75}).*/$1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Atau, dengan GNU sed:

$ sed 's/\(.*\t.\{75\}\).*/\1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Atau:

$ sed -r 's/(.*\t.{75}).*/\1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Atau, Anda bisa menggunakan fold, menyuruhnya memotong pada 91 karakter pertama (itu 8 untuk pengidentifikasi dan 8 lainnya untuk tab), dan mencetak hanya baris pertama:

$ fold -w 91 file | head -n1
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Jika file Anda dapat memiliki lebih dari 2 kolom dan Anda hanya ingin memotong kolom kedua, Anda dapat melakukannya (yang, seperti yang baru saja saya perhatikan, hanyalah penulisan ulang jawaban Stephen ):

$ awk -F"\t" -vOFS="\t" '{$2=substr($2,1,75)}1;' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Atau (perhatikan bahwa ini akan pecah jika 75 karakter pertama dari kolom ke-2 dapat diartikan sebagai ekspresi reguler):

$ perl -F"\t" -pale 's/$F[1]/substr($F[1],0,75)/e' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Mereka mungkin memotong kolom lain dari yang kedua. sedPerintah pertama Anda juga menggunakan GNUism ( \t).
Stéphane Chazelas

@ StéphaneChazelas apa ? \titu GNUisme? Serius? Apa cara portabel untuk menggambarkan tab?
terdon

1
Masukkan kata demi kata untuk melihat jawaban saya. Satu-satunya urutan melarikan diri yang diakui dengan mudah pada LHS adalah \n(dan sekali lagi tidak di dalam [...]dengan banyak implementasi), tidak ada pada RHS.
Stéphane Chazelas

@ StéphaneChazelas, terima kasih. Saya juga menambahkan solusi yang dapat menangani banyak kolom.
terdon

Yang terakhir perltidak masuk akal. Pikirkan misalnya input sepertiaba\t.*
Stéphane Chazelas

10

Menggunakan awk, pisahkan file menggunakan tab dan hasilkan bidang pertama secara penuh dan 75 karakter pertama (paling banyak) dari yang kedua:

awk -F "\t" 'BEGIN { OFS=FS }; { print $1, substr($2, 1, 75); }'

Seperti yang ditunjukkan oleh fedorqui , Anda dapat menangani file dengan lebih dari dua bidang dengan mengganti bidang yang harus Anda potong:

awk -F "\t" 'BEGIN { OFS=FS }; { $2=substr($2, 1, 75); print }'

Anda bisa menerapkannya substrke beberapa bidang dengan mengulanginya jika perlu.


@ Stéphane, dalam hal apa saja yang ;perlu ekstra ?
Stephen Kitt

Mereka diperlukan oleh POSIX. Sekarang saya tidak tahu implementasi apa pun di mana mereka diperlukan, tetapi ketika saya meminta agar persyaratan POSIX dilonggarkan, ditolak oleh pengelola gawk (di mana semua contoh dalam dokumen memiliki;).
Stéphane Chazelas

Ah, senang tahu, terima kasih! Jadi spesifikasi dan dokumentasinya lebih ketat daripada semua implementasinya ...
Stephen Kitt

semua implementasi yang saya tahu setidaknya (tidak begitu banyak). Intinya adalah menghilangkan pembatas yang dibuat untuk sintaksis non-standar. Jadi implementasi saat ini dan di masa depan mungkin dan berhak untuk mencekiknya atau memperkenalkan ekstensi yang memanfaatkannya (seperti pengecualian yang menangani /pattern/ {action} {exception-handling}contohnya). Sekarang itu akan sangat tidak mungkin mengingat bahwa menghilangkan itu ;cukup umum.
Stéphane Chazelas

4

Portable / POSIXly dengan sed:

tab=$(printf '\t')
sed "s/\($tab[^$tab]\{0,75\}\)[^$tab]*/\1/"

Atau untuk memotong setiap kolom:

sed "s/\([^$tab]\{75\}\)[^$tab]*/\1/g"

2

Jika hanya ada 2 kolom:

sed -r 's/^([^\t]*\t)(.{0,75}).*/\1\2/'

{0,75}berarti memilih dari 0 hingga 75 karakter.
.* adalah bagian yang dihapus di luar char 75.


Jika ada 2 kolom atau lebih :

sed -r 's/^([^\t]*\t)([^\t]{0,75})[^\t]*(.*)/\1\2\3/' file

[^\t]* adalah bagian yang dihapus di luar char 75.


Perhatikan bahwa yang mengasumsikan GNU seddan yang POSIXLY_CORRECTtidak di lingkungan ..
Stéphane Chazelas
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.