Inilah yang saya dapatkan dari dokumentasi: \zs
"memulai bagian yang disorot" setelah mencocokkan regex sebelumnya, dan \@<=
"memulai bagian yang disorot" setelah mencocokkan atom sebelumnya . Tapi saya tidak benar-benar memahami seluk-beluk ini, jadi adakah yang bisa menjelaskan bagaimana perbedaannya sedikit lebih dalam?
Inilah yang membuat saya penasaran: apakah saya lari
/\_s\zsnnoremap
yaitu pilih nnoremap
didahului oleh spasi atau garis awal (yaitu baris baru dari garis sebelumnya, maka \_
sebelumnya s
) dan kemudian jalankan gn
untuk masuk ke Mode Visual dan pilih secara visual pertandingan berikutnya, untuk beberapa alasan hanya kolom pertama (yaitu pertama n
masuk nnoremap
) dipilih - terlepas dari kenyataan bahwa seluruh nnoremap
kata disorot dengan :hlsearch
dihidupkan.
Namun, jika saya malah menjalankan pencarian
/\_s\@<=nnoremap
dan kemudian coba gn
, keseluruhannya nnoremap
dipilih dengan benar. Apa yang mungkin terjadi di sini? Apakah saya (berani saya katakan) menemukan beberapa bug yang tidak jelas?
sumber
:h patterns
tetapi ingatan saya menunjukkan bahwa regex terdiri dari atom, jika itu membantu menjelaskan perbedaannya.Jawaban:
Sepertinya Anda memang menemukan bug yang tidak dikenal. Saya telah mengimplementasikan objek
gn
teks pada tahun 2012 untuk Vim 7.3 sesuatu. Ini pada dasarnya bekerja dengan cara berikut:1) Pencarian mundur untuk kecocokan terakhir dari persamaan reguler saat ini.
2) Ia mencari maju untuk kecocokan berikutnya dari persamaan reguler saat ini.
Ini harus menjelaskan, bahwa kursor akan berada di awal pertandingan berikutnya, bahkan jika sudah ada di awal 1).
Akhirnya3) ia mencari akhir dari ekspresi reguler saat ini. dan meletakkan kursor di sana.Sekarang yang terjadi di sini adalah bahwa pencarian untuk akhir pertandingan saat ini membungkus dan bergerak kembali ke akhir pertandingan sebelumnya (karena
wrapscan
sudah ditetapkan, setelah dinonaktifkan untuk 1)). Ini kemudian menetapkan penanda Visual ke area dari awal (akhir poin 2) dan area dipindahkan ke oleh item pencarian berikutnya 3).Saya akan melihat masalah ini lebih dekat dan mungkin akan mengirimkan tambalan untuk Vim nanti.
[Pembaruan 22.05.2018] Saya telah menulis dan mengirimkan tambalan untuk memperbaiki perilaku ini.
[Pembaruan2 22.05.2018] Dan tambalan telah digabung sebagai tambalan level 8.1.0018
[Pembaruan 22.10.2019] Pada Vim patch 8.1.629 langkah ketiga tidak dilakukan lagi. Sebaliknya Vim sekarang dapat menentukan akhir pertandingan ketika menemukan awal pertandingan (Langkah 2)
sumber
Christian telah sepenuhnya menjawab pertanyaan tentang perilaku kereta
gn
, tetapi masih ada perbedaan mendasar antara\zs
dan\@<=
. Makhluk terbesar\@<=
memodifikasi atom sebelumnya, sedangkan\zs
atom adalah diri sendiri.Mempertimbangkan:
Regex 1 cocok, karena
\%1c
cocok dengan kolom 1 dan ada X di sana.\zs
hanya menyebabkan pertandingan dimulai kembali pada posisi setelah X.Namun Regex 2 tidak cocok, karena meskipun
\%1c
cocok dengan kolom pertama,X\@<=
adalah lebar nol (seperti yang disebutkan dalam dokumentasi) dannnoremap
dimulai pada kolom 2. Tidak ada yang membuat perbedaan posisi antara kolom 1 dan 2.Regex 3 cocok sejak
nnoremap
dimulai pada kolom 2.sumber
nnoremap
dari regex akan menghasilkan kecocokan; tetapi regex masih gagal bahkan tanpa. Saya pikir itu gagal karena\%1cX\@<=
menyatakan suatu posisi yang tidak mungkin ada.\%1c
cocok dengan posisi di kolom 1, danX\@<=
meminta karakter yangX
cocok sebelum itu. Tetapi tidak ada karakter apa pun sebelum kolom pertama. Itulah sebabnya, bahkan jika Anda menggantiX
dengan titik (karakter apa pun), regex\%1c.\@<=
masih gagal.\zs
berlaku untuk seluruh ekspresi reguler, dan menetapkan karakter berikutnya menjadi karakter pertama dari seluruh pertandingan. Apa pun sebelum\zs
tidak akan dimasukkan sebagai bagian dari teks yang cocok.\@<=
, di sisi lain, hanya memengaruhi atom-atom langsung di sekitarnya, memungkinkan Anda menentukan bahwa atom berikutnya hanya akan cocok jika mengikuti atom sebelumnya. Jadi misalnya, ekspresi reguler:Akan mencocokkan semua teks antara dua instance dari
bar
(termasuk instance itu sendiri), tetapi hanya jika yang kedua didahului olehfoo
. yaitu, itu akan cocok dengan:tapi tidak:
Karena
\@<=
dilokalisasi dengan cara ini, Anda bahkan dapat menggunakan\@<=
beberapa kali dalam satu ekspresi:Berikut ini akan cocok dengan tiga contoh
bar
, tetapi hanya jika dua yang kedua masing-masing didahului olehfoo
.yaitu diberi teks:
Ini akan cocok dengan baris pertama saja.
sumber
\zs
, yaitu, ini juga harus bekerja:\vfoo\zsbar.*(foo)@<=bar
.\zs
tidak dapat diganti sama sekali.\zs
dan\ze
bisa diganti dengan melihat-lihat pola regex, dan mereka lebih kuat, bukan? Penyebab yang lebih kuat dapat digunakan lebih dari sekali dan dapat dikelompokkan\(\)
. Dan juga karena mereka bekerja seperti perl melihat-lihat regex. Adakah yang salah?\zs
/\ze
ketika Anda bisa, karena mereka lebih cepat daripada melihat-lihat.\zs
dan\ze
jelas lebih intuitif. Terima kasih atas penjelasannya.