Bagaimana cara menambahkan nomor baris permanen ke file?


22

Saya memiliki file teks seperti ini (menggunakan gVim di Windows)

foo bar baz quux 
corge grault garply 
waldo fred plugh 
[...150 more lines...]
xyzzy thud

Saya ingin menambahkan nomor ke setiap baris dalam file. Tidak menggunakan :set number, tetapi untuk menambahkan nomor sebagai teks sebelum setiap baris, sebagai berikut, sehingga nomor tersebut merupakan bagian dari file.

1. foo bar baz quux 
2. corge grault garply 
3. waldo fred plugh 
[...~150 more lines...]
155. xyzzy thud

awkmungkin alat untuk pekerjaan ini. Tapi saya di Windows (menghela napas).
roblogic

Sudah dijawab di sini , sudahlah :)
roblogic

1
Mungkin .. Atau ini lebih umum?
muru

Ini mirip, tetapi saya tidak akan tahu apa itu nomor saluran permanen. Kedua pertanyaan lain adalah tentang semua baris (dan jawabannya tidak) untuk gVim pada Windows secara khusus dan ini adalah daftar bernomor sederhana untuk satu paragraf hanya dalam vim polos.
kenorb

3
Yah, saya kira posting itu menggunakan "permanen" atau menunjukkan bahwa buffer harus dimodifikasi, dan bahwa angka-angka itu bukan sesuatu yang murni visual (sama seperti Anda). Alasan untuk menentukan gvim pada Windows adalah untuk menghindari utilitas eksternal seperti catatau nl, yang dapat melakukan garis bilangan, tetapi umumnya tidak tersedia pada Windows (seperti yang ditunjukkan OP dari komentar mereka tentang awk). Dua solusi teratas adalah Vim murni. Terakhir, semua baris vs satu para hanya masalah pemilihan rentang. Jelas bukan masalah besar.
muru

Jawaban:


37

Dalam mode Vim murni:

:%s/^/\=line('.').". "

Penjelasan:

:%s/^/            " the substitution will be applied to the beginning of every line
\=                " the rest of the replacement part is an expression
line('.').". "    " the expression returns the current line number concatenated with a dot and a space

Lihat :help \=dan :help line().

Menggunakan ekspresi di bagian pengganti sangat kuat dan FWIW titik masuk yang cukup bagus ke vimscript.


Bagaimana saya bisa menambahkan perintah yang sangat berguna ini ke keapap di vimrc?
cosmicraga

Untuk sampai ke topik bantuan vim untuk substitusi::help sub-replace-expression
akurtser

9

Satu hal yang menyenangkan tentang Vim macro adalah mereka dapat berulang (mereka dapat memanggil diri mereka sendiri):

  1. Hapus register q: qqq
  2. Tambahkan nomor ke baris pertama: ggI1.(jangan lupa spasi!)
  3. Kembali ke awal baris dan mulai merekam makro: 0qq
  4. Salin nomornya: yW
  5. Turunkan satu baris dan tempel nomornya: +P
  6. Pindah kembali ke awal baris dan tambahkan nomornya: 0<c-a>
  7. Kembalilah ke awal baris (sehingga makro tidak pecah ketika sampai dua kali lipat angka!): 0
  8. Panggil makro sekali, untuk membuatnya rekursif. Pada titik ini, masih ada apa-apa dalam register q, sehingga tidak akan terjadi: @q.
  9. Simpan makro: q
  10. Panggil makro sekali lagi, dan saksikan bunga api beterbangan !: @@

Makro kemudian akan terus memohon sendiri hingga mencapai akhir file.

Anda dapat menggunakan trik makro rekursif untuk banyak masalah serupa lainnya, jadi ini baik untuk diperhatikan.

Jika Anda tidak ingin menggunakan makro rekursif karena suatu alasan, Anda bisa menghilangkan langkah 1 dan 8, dan menggunakan hitungan untuk menjalankan makro berkali-kali, misalnya 100@qakan menjalankan makro q100 kali.


1
Hal-hal yang kuat, saya tunduk pada penguasaan Anda. Makro seperti ilmu hitam bagiku ...
roblogic

1
@ropata, makro hanya urutan (kebanyakan) perintah mode normal.
romainl

1
@romainl Saya pikir lebih baik memikirkannya sebagai urutan penekanan tombol .
Kaya

2
@ Kaya, itu bisa menjadi urutan banyak hal, termasuk perintah ex.
romainl

2
@romainl Ya, itu sebabnya saya pikir yang terbaik adalah menganggapnya sebagai penekanan tombol. Memutar ulang persis apa yang Anda ketikkan pada keyboard (termasuk, seperti yang Anda katakan, perintah ex), seolah-olah Anda telah mengetik semuanya secara manual.
Kaya

7

Saya suka menggunakan perintah global vim untuk menyelesaikan tugas-tugas seperti ini. Ini berlaku untuk menambahkan iterasi ke awal baris atau memodifikasi simbol dalam teks. Ini terlihat lebih rumit daripada solusi lain, tetapi merupakan pola yang cukup fleksibel untuk digunakan saat Anda menggunakannya, dan mudah untuk dimodifikasi tanpa banyak pemikiran.

Pertama, pilih rentang Anda (baris mana yang ingin Anda terapkan ini). Saya biasanya menggunakan tanda (misalnya mapada baris pertama dan mbpada baris kedua, tetapi Anda juga dapat menggunakan nomor baris atau pemilihan visual), kemudian masukkan modifikasi dari perintah berikut (saat ini di-tweak untuk use case Anda)

:let i=1|'a,'bg/^/s/^/\=i.". "/|let i=i+1

Dekonstruksi

:let i=1

Ini mengatur variabel idengan nilai awal. Biasanya daftar dimulai dengan 1, jadi saya mengatur i ke 1.

|

Bilah memulai perintah baru

'a,'b

Ini mengatur rentang perintah selanjutnya. Saya beralih dari satu tanda ake tanda lainnya b, yang akan ditetapkan pada baris pertama dan baris terakhir dari daftar Anda.

g/^/

Ini adalah perintah global. Itu mencari file (atau rentang) untuk ekspresi reguler yang diberikan, dan akan mengeksekusi sisa baris perintah pada setiap baris yang cocok. Saya mencocokkan setiap baris dengan mencari "awal baris". Jika Anda memiliki teks suka

Item some txt
other text

Item second item
whatever
Item third

dan hanya ingin meletakkan label ini di depan Itemdan mengabaikan baris lain, lakukan g/Item/atau g/^Item/sebaliknya (dengan asumsi teks Item literal)

s/^/\=i.". "/

Ini mengeksekusi ekspresi reguler untuk mengganti awal baris dengan nilai idigabungkan dengan a .. Secara umum Anda dapat melakukan ini untuk apa saja (ganti label Itemdengan nomor, misalnya).

|let i=i+1

Meskipun bilah memulai perintah baru, bilah ini mengatur perintah kedua untuk dijalankan di dalam perintah global, alih-alih setelah global selesai. Hasilnya adalah kita bertambah isebelum baris berikutnya diproses oleh g. Di sini ada tempat lain untuk fleksibilitas. Modifikasi i dapat berupa apa saja (selisih 2, sebut fungsi yang menghasilkan elemen berikutnya dari deret Fibonacci, apa pun).


7

Tambahkan angka ke semua baris

Mungkin untuk menggunakan :%!nl -baatau :%!cat -nperintah yang akan menambahkan nomor baris ke semua baris.

Di Windows, Anda harus menginstal Cygwin / MSYS / SUA.

Tambahkan angka ke baris yang dipilih

Untuk menambahkan angka hanya untuk baris yang dipilih, silakan pilih dalam mode visual ( vdan kursor), kemudian ketika selesai - jalankan perintah: :%!nl(abaikan baris kosong) atau :%!cat -n(baris kosong disertakan).

Memformat

Untuk menghapus spasi tambahan, pilih di blok visual ( Ctrl+ v) dan hapus ( x).

Untuk menambahkan beberapa karakter ( ., :, )) setelah nomor, pilih mereka dalam blok visual ( Ctrl+ v), kemudian tambahkan karakter ( A, ketik karakter, kemudian menyelesaikan dengan Esc).


2
Ini tidak memberikan format yang sama seperti yang diberikan dalam pertanyaan. Namun, saya suka kesederhanaan solusinya.
Karl Yngve Lervåg

@ KarlYngveLervåg Terima kasih, termasuk dalam jawaban.
kenorb

5

Modifikasi jawaban romainl :

:%s/^\(\d\+\. \)\?/\=line('.').". "

Ini tidak hanya akan menambahkan nomor baris, itu juga akan menggantikan nomor baris yang sudah ada di sana. Tentu, jika Anda memasukkan garis di tengah jalan, itu akan memberi nomor baru semuanya seperti yang diharapkan.

Ini berfungsi dengan mengganti angka apa saja yang diikuti oleh a. dan spasi di awal baris dengan nomor baru. Ini jelas akan pecah jika Anda memiliki garis yang sudah dimulai dengan pola ini, jadi gunakan dengan pemikiran.

Bagian yang ditambahkan:

  • ^ - Mulai dari garis
  • \( - Mulai subkelompok baru
  • \d\+ - Cocokkan satu digit sekali atau lebih
  • \. - Cocokkan titik ( .) dan spasi .
  • \) - Akhiri subkelompok
  • \? - Jadikan grup opsional, sehingga berfungsi seperti sebelumnya jika belum ada nomor pada baris ini.

Petunjuk bonus:
Untuk menghapus nomor baris, Anda dapat menggunakan pola yang sama dengan bagian repalce kosong:

:%s/^\(\d\+\. \)\?//

5
I1. <esc>^qqyWjP^<C-a>q

Ini nomor dua baris pertama, dan Anda dapat menekan @qke nomor baris berikutnya (atau ketik ex. 18@qJika Anda ingin nomor 20 baris total).

Penjelasan:

I1. <esc>  Number the first line
hqq        Go back to the start of the line and start recording a macro
yWjP       Copy the line number to the next line
^<C-a>     Increment the next line's line number
q          Finish recording

Manfaatnya adalah tidak memerlukan perintah eksternal, yang berguna jika Anda bekerja dengan Vim di Windows, misalnya.


Setelah mengetik 1. <esc>hAnda berada di kolom kedua, bukan kolom pertama. Saya akan mengganti hdengan 0, setelah itu saya pikir solusi Anda harus sangat bagus.
Karl Yngve Lervåg

@ KarlYngveLervåg Whoops, itu salah ketik. Terima kasih, perbaiki.
Gagang pintu

Tidak masalah. Namun, Anda masih belum memperbarui penjelasannya. Juga: Pada banyak keyboard, ^tunggu karakter kedua untuk memungkinkan kombinasi pengetikan seperti ^a -> â. Saya masih setuju ini solusi terbaik, tetapi saya pikir ini harus disebutkan juga.
Karl Yngve Lervåg

3

Saya pikir jawaban yang dipilih adalah yang terbaik, tetapi dalam sprit of variety, saya akan menawarkan alternatif menggunakan program eksternal:

:%!cat -n

Ini akan memfilter seluruh buffer Anda (sebagaimana dilambangkan oleh %) melalui program eksternal cat,, di mana -nflag mendahului setiap baris input dengan nomor baris.

Ini, tentu saja, mengharuskan Anda catmenginstal, yang berlaku untuk (mungkin) semua sistem mirip Unix.

Lihat :help :range!detail selengkapnya tentang pemfilteran melalui program eksternal.


1
Saya menyadari bahwa penanya menggunakan gVim di Windows, jadi solusi ini mungkin tidak akan berfungsi di sana. Namun, saya pikir itu masih memberikan beberapa peluang bagi orang lain untuk belajar darinya.
tommcdo

Jika Anda telah menginstal msysgitdan menambahkannya ke PATH Anda (IIRC ini adalah opsi instal), solusi ini juga harus bekerja pada Windows.
Martin Tournoij

4
cat -nbukan POSIX, tetapi nl, jadi itu mungkin pilihan yang lebih baik.
muru

2

Solusi sedikit meretas mungkin sebagai berikut (semua yang ditulis antara <dan> harus dimasukkan setelah menekan Ctrl+ v):

:%normal :redir @"<Enter>:-=<Enter>:redir END<Enter>I<C-R>".<Tab><Esc>kdd

Dekonstruksi

:%normal {commands}

menjalankan perintah mode normal pada setiap baris yang ditentukan oleh rentang, dalam hal ini setiap baris

:redir @"

mengalihkan setiap output yang dibuat oleh perintah ex ke buffer tanpa nama.

:.=

adalah perintah ex yang menampilkan nomor baris saat ini (sayangnya, baris baru sebelumnya)

:redir END

berhenti mengarahkan ulang ke buffer yang tidak disebutkan namanya

I<C-R>".<Tab><Esc>

menyisipkan konten buffer tanpa nama dengan a. dan tab untuk ke depan setiap baris dan keluar dari mode insert.

kdd

berjalan satu baris ke atas dan menghapus baris baru yang merupakan hasil dari perintah:. =

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.