Saya ingin menghapus kolom terakhir dari file txt, sementara saya tidak tahu apa nomor kolomnya. Bagaimana saya bisa melakukan ini?
Contoh:
Memasukkan:
1223 1234 1323 ... 2222 123
1233 1234 1233 ... 3444 125
0000 5553 3455 ... 2334 222
Dan saya ingin hasil saya menjadi:
1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334
text-processing
sed
awk
perl
zara
sumber
sumber
Jawaban:
Dengan
awk
:atau:
atau:
Meskipun ini terlihat seperti voodoo, ia berfungsi. Ada tiga bagian untuk masing-masing perintah awk ini.
Yang pertama adalah
NF
, yang merupakan prasyarat untuk bagian kedua.NF
adalah variabel yang berisi jumlah bidang dalam satu baris. Di AWK, semuanya benar jika bukan 0 atau string kosong""
. Oleh karena itu, bagian kedua (di manaNF
dikurangi) hanya terjadi jikaNF
tidak 0.Bagian kedua (baik
NF-=1
NF--
atau--NF
) hanya mengurangi satu dariNF
variabel. Ini mencegah bidang terakhir dari dicetak, karena ketika Anda mengubah bidang (menghapus bidang terakhir dalam kasus ini),awk
membangun kembali$0
, menggabungkan semua bidang yang dipisahkan oleh ruang secara default.$0
tidak mengandung bidang terakhir lagi.Bagian terakhir adalah
1
. Itu tidak ajaib, hanya digunakan sebagai ungkapan yang berartitrue
. Jikaawk
ekspresi bernilai true tanpa tindakan yang terkait,awk
tindakan default adalahprint $0
.sumber
--
. Sebuah catatan, saat ini, Anda butuhkan;1
untuk mematuhi POSIX.,
adalah pembatas Anda:awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out
Menggunakan
grep
dengan PCRE:Menggunakan GNU
sed
:sumber
Menggunakan Perl:
Menggunakan
rev
+cut
:sumber
Menggunakan GNU sed:
Secara umum, ini bekerja dengan BSD sed di OSX, dan juga GNU sed:
sumber
Jika pembatas selalu berupa char tunggal (jadi dua atau lebih pembatas berturut-turut menunjuk bidang kosong), Anda bisa
head
menggunakan baris pertama dari file input Anda, menghitung pembatas (n
pembatas berarti jumlah bidangn+1
), kemudian gunakancut
untuk mencetak dari1
bidang st. hinggan
bidang ke - th (kedua ke terakhir), mis. dengan input yang dibatasi-tab:atau misalnya dengan file csv :
Saya akan menjalankan beberapa tolok ukur nanti jika saya punya waktu tetapi dengan input besar saya pikir solusi ini harus lebih cepat daripada solusi lain yang menggunakan regex karena yang satu ini melakukan pemrosesan minimal pada baris pertama untuk mendapatkan no. bidang dan kemudian menggunakan
cut
yang dioptimalkan untuk pekerjaan ini.sumber
Portable Anda dapat menggunakan salah satu dari ini:
sumber
Menggunakan vim:
Buka file dalam vim
Pergi ke baris pertama, kalau-kalau kursor ditempatkan di tempat lain.
Buat makro bernama "q"
qq
, yang pergi ke belakang garis saat ini$
, kemudian kembali ke ruang terakhirF
(modal F, diikuti oleh SPACE literal) kemudian hapus dari posisi saat ini sampai akhir barisD
turun ke baris berikutnyaj
dan hentikan perekaman makro denganq
.Sekarang kita bisa mengulang makro kita dengan
@q
untuk setiap baris.Kami juga dapat menekan
@@
untuk mengulangi makro terakhir atau bahkan lebih mudah:untuk mengulang makro 99 kali.
Catatan: Jumlahnya harus tidak sama persis dengan garis.
sumber
Untuk orang-orang yang memiliki masalah serupa tetapi dengan pemisah lapangan yang berbeda
awk
metode ini akan menjaga pemisah lapangan dengan benar:sumber