Bagaimana saya bisa menjalankan: mengganti hanya sebagian dari garis dan tidak semuanya?

15

Saya memiliki garis seperti ini:

function my_function(argument, another argument, but there are spaces)

Saya ingin mengganti karakter spasi (di dalam nama argumen) dengan garis bawah. Dengan demikian saya ingin menggunakan:

:s/\ /_/g

tetapi bagaimana saya bisa memilih untuk tidak menerapkannya ke seluruh baris, tetapi mulai dari, katakanlah, posisi kursor? (Atau kata ketiga)?

Feffe
sumber
4
Dalam regex, untuk menggambarkan posisi kursor saat ini, Anda dapat menggunakan atom \%#. Jadi, Anda bisa menggunakan: :s/\v(%#.*)@<= /_/g. Yang bisa digambarkan sebagai spasi diawali oleh ( @<=) karakter setelah posisi kursor.
user9433424
1
Anda dan Statox sama-sama mengusulkan \%#trik, saya akan menerima jawabannya jika Anda tidak menulis satu pun ... Tapi bisakah kalian menjelaskan regexp dengan sedikit lebih eksplisit?
Feffe

Jawaban:

15

Anda dapat menggunakan solusi berikut:

Pertama digunakan v$untuk memilih teks dari kursor ke akhir baris. Kemudian gunakan perintah berikut:

:s/\%V\ /_/g

The \%Vmengindikasikan untuk mengubah teks di daerah yang sebelumnya visual yang dipilih, lihat :h /\%V.

Jika saya ambil contoh Anda:

function my_function(argument, another argument, but there are spaces)

Jika kursor saya ada di kolom ke-40 dan saya menggunakan perintah yang baru saya tulis, saya dapat

function my_function(argument, another argument,_but_there_are_spaces)

Sebagai jawaban atas komentar Anda, Anda juga dapat menggunakan

  • \%# yang cocok dari posisi kursor
  • \%>23c yang cocok setelah kolom ke-23.
  • \%>'m yang cocok setelah posisi tanda

Lihat :h /\%#, :h /\%>cdan :h /\%>'m.

@ User9433424 memberi cara untuk digunakan \%#dalam komentarnya. Untuk pola dengan tanda, Anda dapat mengaturnya dengan akal madan kemudian menggunakan:

:s/\%>'a /_/g

Penjelasan tentang pola yang diberikan oleh @ User9433424 adalah sebagai berikut:

:s/\v(%#.*)@<= /_/
:s/                    substitution command
   \v                  Enable the very magic mode
      %#.*             Any characters from the cursor position
           @<=         Check for matches just before what follows
              space    Followed by a space
               /_/     Substitute the matches by underscores

Anda akan ingin melihat :h \vdan:h /\@<=

statox
sumber
Ini bekerja dengan baik! Tapi saya tidak terlalu terbiasa dengan pilihan visual dan keseluruhan prosesnya agak "berat" ... Apakah Anda pikir mungkin ada sesuatu yang lebih cepat?
Feffe
Ya, izinkan saya memperbarui jawaban saya :)
statox
User9433424 memberikan petunjuk ini tepat sebelum Anda, tetapi Anda menjawab jadi saya akan menerima jawaban Anda jika tidak apa-apa - bisakah Anda menjelaskan pola regexp yang ia gunakan sedikit lebih banyak? Saya masih berjuang dengan ini ...
Feffe
Saya mencoba membuat jawabannya sejelas mungkin tetapi jika @ User9433424 menulis jawabannya sendiri jangan ragu untuk menerimanya.
statox
1
Penjelasan yang sangat bagus dari regexp, terima kasih! Dan terima kasih atas komentar Anda yang jawabannya diterima :)
Feffe
5

Anda dapat menggunakan tampilan di belakang ( :h \@<=) untuk memastikan ada '(', dan batas akhir kata sebelumnya :h \>) untuk memastikan substitusi terjadi di tempat yang Anda inginkan.

Jadi, dengan teks:

function my_function(argument, another argument, but there are spaces)

menjalankan perintah:

:s/\((.*\)\@<=\> /_/g

akan menghasilkan:

function my_function(argument, another_argument, but_there_are_spaces)

Ini mungkin lebih mudah daripada harus memposisikan kursor setiap kali, asalkan substitusi selalu memiliki titik awal yang diketahui.

Antony
sumber
2
Substitusi tidak selalu memiliki titik awal yang diketahui: itu hanya untuk ... memperbaiki serangkaian kesalahan ketik yang saya buat. Namun jawaban Anda tetap menarik, terima kasih!
Feffe