Cara menyalin setiap baris 11 kali, menambah "1" terakhir di setiap baris dari 2-12

9

Saya memiliki sejumlah baris dalam file, dan saya ingin menyalin setiap baris 11 kali (mengubah setiap baris menjadi 12 baris), dan menambahkan "1" terakhir di setiap baris sehingga 12 baris memiliki "1" hingga " 12 ", di mana" 1 "awalnya berada. Mungkin ada kejadian lain dari "1" di setiap baris, tetapi "1" yang ingin saya tambahkan akan selalu menjadi kejadian terakhir di setiap baris. Cara lain untuk melihatnya adalah "1" terakhir selalu setelah "/ nt /" - seperti pada "/ nt / 1" (dan itu akan selalu menjadi satu-satunya kejadian "/ nt / 1" di setiap baris) .

Jadi, misalnya, jika saya punya:

1stlineblahblahblah/nt/1blah
2ndlineblahblahblah/nt/1blah
3rdlineblahblahblah/nt/1blah

Saya ingin mengubahnya menjadi:

1stlineblahblahblah/nt/1blah
1stlineblahblahblah/nt/2blah
1stlineblahblahblah/nt/3blah
1stlineblahblahblah/nt/4blah
1stlineblahblahblah/nt/5blah
1stlineblahblahblah/nt/6blah
1stlineblahblahblah/nt/7blah
1stlineblahblahblah/nt/8blah
1stlineblahblahblah/nt/9blah
1stlineblahblahblah/nt/10blah
1stlineblahblahblah/nt/11blah
1stlineblahblahblah/nt/12blah
2ndlineblahblahblah/nt/1blah
2ndlineblahblahblah/nt/2blah
2ndlineblahblahblah/nt/3blah
...

Saya sebelumnya telah menemukan perintah:

:for i in range(0,12) | put ='1stlineblahblahblah/nt/'.i.'blah' | endfor

berfungsi untuk tujuan ini, tetapi saya harus secara manual menjalankan perintah ini untuk setiap baris, dan ketik setiap baris di (atau salin dan tempel) sendiri. Apakah ada cara untuk mengambil baris yang sudah ada dalam file, dan jalankan saja satu perintah yang mengubah setiap baris menjadi dua belas, dengan cara yang telah saya jelaskan?

Terima kasih sebelumnya kepada siapa saja yang dapat membantu saya dengan ini. Saya juga hanya ingin mencatat bahwa ini adalah pertanyaan kedua saya di sini, dan saya senang mendapatkan beberapa solusi cepat dan efektif untuk pertanyaan pertama saya, yang paling saya syukuri.

ablewasiereisawelba
sumber

Jawaban:

8

Inilah substitusi yang memecahkan masalah:

:%s/\(.*\)1\(.*\)/\=join(map(range(1, 12), 'submatch(1) . v:val . submatch(2)'), "\n")

Substitusi cocok dengan setiap baris yang berisi "1" dan menangkap teks sebelum {c1}dan sesudah {c2}"1" terakhir. Untuk setiap baris cocok, kisaran angka 1-12 {n}yang dipetakan untuk membuat dua belas baris formulir {c1}{n}{c2}. Setiap kelompok yang terdiri dari dua belas baris menggantikan garis yang terkait dan aslinya cocok.

Lihat :h sub-replace-expression.

djjcast
sumber
2
Wow, perintah satu baris yang bagus. Saya ingat bahwa Anda juga menemukan solusi satu baris yang elegan untuk pertanyaan pertama yang saya tanyakan beberapa minggu yang lalu. Kerja yang sangat bagus. Terima kasih banyak. Juga, saya kira ada cara untuk meletakkan ini di file _vimrc sehingga saya dapat menjalankan perintah atau fungsi yang mudah diingat tanpa mengetikkan seluruh baris di atas (atau harus menelusuri daftar perintah sebelumnya), tetapi Saya belum cukup akrab dengan sintaks _vimrc untuk mengetahui bagaimana melakukannya.
ablewasiereisawelba
10

Anda bisa melakukannya dengan

  1. merekam makro, lalu
  2. menggunakan globalperintah ex untuk menjalankan makro n beberapa kali untuk setiap baris dalam file.

Setelah merekam makro, batalkan perubahan yang dilakukan saat merekam, atau akan ada n + 1 baris tambahan untuk baris pertama, dan n untuk baris berturut-turut.

Rekam makro ke aregister dengan

qayyp$?\d<CR><C-A>q

Ini mencatat ke register a( qa...q) perintah berikut:

  • yyp: duplikat baris saat ini
  • $: pindah ke akhir baris
  • ?\d<CR>: cari mundur satu digit
  • <C-A>: increment digit di bawah kursor per satu

Saat makro direkam, hapus perubahan yang dibuat saat merekamnya dengan membatalkan ( uu) atau dengan menghapus baris saat ini ( dd). Kemudian ulangi makro 11(atau berapa kali) kali untuk setiap baris dalam file dengan perintah global:

:g//normal 11@a
jjaderberg
sumber
2
Berhasil! Sangat baik terima kasih. Awalnya saya punya masalah dengan Ctrl-a menyoroti semuanya alih-alih menambahkan, karena saya menggunakan gVim di Windows ... tapi saya melakukan pencarian cepat dan menemukan utas ini - stackoverflow.com/questions/289681/… - di mana saya menggunakan saran meletakkan nnoremap <kPlus> <Ca> nnoremap <kMinus> <Cx> di _vimrc sehingga saya dapat menggunakan kunci "+" dan "-" untuk menambah dan mengurangi. Juga, perintah global harus: g // normal 11 @ a untuk saya, tapi itu mudah dipecahkan. Terima kasih!
ablewasiereisawelba
6

Dua arah:

Gunakan makro!

Dimulai dengan

1stlineblahblahblah/nt/1blah
2ndlineblahblahblah/nt/1blah
3rdlineblahblahblah/nt/1blah

Dengan kursor Anda di baris pertama

qqyyp$?\d<CR><Ctrl-a>q
10@q

Yang tidak:

qq Mulai merekam makro ke dalam register q

yyp tarik garis saat ini, dan rekatkan di bawah ini

$?\d<CR> Pergi ke akhir baris, dan temukan digit pertama yang melihat ke belakang

<Ctrl-a> Tambahkan nomornya

q Berhenti merekam makro.

Ini membuat Anda dengan:

1stlineblahblahblah/nt/1blah
1stlineblahblahblah/nt/2blah
2ndlineblahblahblah/nt/2blah
2ndlineblahblahblah/nt/3blah

Dengan kursor di baris kedua. Cukup ulangi makro ini sebanyak yang diinginkan (Misalnya, ulangi sepuluh kali dengan 10 @ q). Jika Anda ingin mengotomatiskan proses ini untuk setiap baris, jalankan secara global di setiap baris:

:g//normal 11@q

Atau, dengan versi vim yang lebih baru: Tempel garis yang Anda inginkan namun berkali-kali, blok visual pilih digit yang ingin Anda tambahkan, dan tekan g <Ctrl-a>. Ini harus menambah semua angka di blok visual sesuai keinginan Anda. Namun ini adalah proses yang lebih manual.

fruglemonkey
sumber
1
Luar biasa, saya tidak tahu tentang g <c-a>caranya. Terima kasih telah berbagi.
kba berdiri bersama Monica
1
@ fruglemonkey Bagian pertama dari jawaban Anda sama dengan yang di atas, tapi tetap saja terima kasih. Bagian kedua, saya pikir tidak berfungsi untuk saya (kecuali saya melakukan sesuatu yang salah), jadi saya tidak boleh menggunakan versi yang benar.
ablewasiereisawelba
5

Saya merasa paling mudah untuk menggunakan makro untuk tugas sekali pakai seperti itu. Mulailah merekam makro dengan q+ nama register dan lakukan tugas sekali. Saya melihat satu tugas berulang di sini:

  • Pilih jalurnya
  • merenggut
  • tempel (akan menempatkan Anda di baris berikutnya)
  • pergi ke akhir baris
  • kembali satu kata
  • selisih satu

Sekarang, rekam penekanan tombol yang diperlukan untuk mendaftar a, dalam mode normal:

qayyp$b<c-a>.

Hapus baris lagi untuk menguji apakah mengeksekusi makro 11 kali menghasilkan hasil yang tepat untuk satu baris:

11@a

Itu benar! Jadi mari undo lagi dan mengotomatiskan seluruh proses dalam makro kedua b:

qb11@aj

Sekarang Anda dapat mengeksekusi @bsampai akhir file dan itu akan menghasilkan output yang Anda inginkan. Kedengarannya rumit tetapi sebenarnya tidak begitu Anda terbiasa dengan pola pengeditan yang khas.

kba berdiri dengan Monica
sumber
Saya tidak yakin jika saya melakukan sesuatu yang salah, tetapi sepertinya tidak berhasil. Saya mengikuti apa yang Anda tulis, tetapi mungkin saya salah mengerti sesuatu atau tidak menjalankan sesuatu dengan benar. (Saya mendapatkan nomor pertama dari baris yang bertambah, bukan nomor terakhir dari baris tersebut.) Terima kasih telah membalas.
ablewasiereisawelba
3
Saya pikir makro pertama seharusnya qaVyp$b<c-a>. Atau lebih baik, hanya qayyp$b<c-a>.
Karl Yngve Lervåg
1
Terima kasih, @ KarlYngveLervåg, Anda benar, saya memperbaiki makro.
Kba berdiri dengan Monica
2
. Argh :( terima kasih untuk menjadi @ablewasiereisawelba menyeluruh Saya kira makro qqyyp$?\d<CR><Ctrl-a>qoleh @fruglemonkey dan @jjaderberg lebih baik karena mencari nomor terakhir saya akan mengubahnya untuk kelengkapan..
KBA berdiri dengan Monica
2
@ kba Saya hanya berpikir bahwa jika ada orang yang meluangkan waktu dan upaya untuk menjawab pertanyaan saya, saya setidaknya bisa mencoba solusinya - bahkan jika saya sudah menemukan solusi yang berfungsi dari orang lain. Saya menghargai upaya Anda - dan jika itu membuat Anda merasa lebih baik, Anda masih jauh di depan saya. :)
ablewasiereisawelba
2

Simpan makro berikut dan gunakan untuk setiap baris:

qqyy11p/\/\zs1<CR><C-v>10jg<C-a>q

Perbedaan utama dari jawaban lain adalah bahwa hal ini digunakan g<C-a>pada pemilihan kolom yang menambah setiap baris dengan nomor yang berbeda. Periksa :help v_g_CTRL-Ainformasi lebih lanjut. Saya juga terbiasa \zsmemilih posisi awal pola, sehingga kursor berhenti pada nomor setelah pencarian.

Harap dicatat bahwa Anda memerlukan versi terbaru Vim agar ini berfungsi.

Vitor
sumber
1
@ fruglemonkey mengusulkan itu juga . Ini adalah fitur keren, meskipun ini cukup baru (dengan standar vim), sejak 7.4.754 yang belum dikirim ke semua distro.
Kba berdiri dengan Monica
Ketinggalan, maaf
Vitor
1
@Vitor Saya baru saja punya gVim 7.4 jadi saya tidak berpikir saya bisa melakukan g<C-a>itu @fruglemonkey dan Anda merujuk, tapi terima kasih telah merespons. Saya harus mencatat bahwa ketika mencoba makro Anda - tepat sebelum saya sampai ke g<C-a>bagian, itu bukan karakter "1" terakhir yang saya ingin selesaikan yang mendapat blok-highlight, tetapi karakternya sebelum yang pertama "1 "karakter yang disorot blok. (Juga, saya pikir itu akan terjadi yy11pdan 10jdalam makro, karena saya ingin menambahkan 11 baris - untuk total 12.)
ablewasiereisawelba
1
Terima kasih atas tanggapan Anda. Saya telah memperbarui jawabannya. Memutuskan untuk menggunakan \zs, tetapi saya bisa saja menambahkan lsetelah <CR>.
Vitor
1
Anda mungkin memiliki beberapa pengaturan di vimrc Anda yang memengaruhi pencarian ekspresi reguler. Coba lagi mulai Vim dengan vim -u NONE. Saya baru saja melakukan itu dan ini bekerja dengan sempurna! Bahkan, tidak mungkin pencarian akan cocok dengan 1 pertama karena membutuhkan garis miring sebelumnya.
Vitor