Vim normal ifadesindeki '\ zs' ve '\ @ <=' atomları arasındaki fark nedir?


13

Belgelerden aldığım budur: \zsönceki regex ile eşleştikten sonra \@<="vurgulanan kısmı başlatır" ve önceki atom eşleştirildikten sonra "vurgulanan kısmı başlatır" . Ama bunun inceliklerini tam olarak anlayamıyorum, bu yüzden nasıl derinlemesine biraz daha farklı olduklarını açıklayabilir mi?

Beni meraklandıran şey buydu: eğer koşarsam

/\_s\zsnnoremap

yani seçeneğini nnoremapbir boşluk veya bir başlangıç-of-line öncesinde (yani önceki çizgisinden satır, dolayısıyla \_önceki s) daha sonra ve çalıştırın gnGörsel Mod girmek için görsel seçmek nedense, sonraki eşleşmeyi sadece ilk sütunu (yani ilk nyılında nnoremap) seçildiği - tüm olmasına rağmen nnoremapkelime olduğu vurgulanan ile :hlsearchdöndü.

Ancak, bunun yerine aramayı çalıştırırsam

/\_s\@<=nnoremap

ve sonra deneyin gn, tüm nnoremapuygun şekilde seçilir. Burada neler olabilir? Belirsiz bir hata keşfetmeye cesaret ettim mi?


Sanırım :h patternsiçeride ama hafızam regex'lerin atomlardan oluştuğunu gösteriyor, eğer bu farkı açıklamaya yardımcı oluyorsa.
D. Ben Knoble

Yanıtlar:


16

Görünüşe göre bu gerçekten belirsiz bir hata buldunuz. Ben uygulayan gnVim 7.3 şey için 2012 yılında textobject geri. Temel olarak aşağıdaki şekilde çalışır:

1) Geçerli normal ifadenin son eşleşmesini geriye doğru arar.

2) Geçerli normal ifadenin bir sonraki eşleşmesini arar.

Bu açıktır ki, imleç bir sonraki maçın başlangıcında olacaktır (1'in başında bile olsa). En sonunda

3) geçerli normal ifadenin sonunu arar. ve imleci oraya koyar.

Şimdi burada olan, şu anki maçın sonunu aramanın bir önceki maçın sonuna doğru kayması ve geri dönmesidir (çünkü wrapscan1 için devre dışı bırakıldıktan sonra zaten ayarlanmıştır). Daha sonra Görsel işaretçiyi başlangıçtan (nokta 2 sonu) ve sonraki arama öğesi 3 tarafından taşınan alana ayarlar.

Soruna daha yakından bakacağım ve muhtemelen Vim için daha sonra bir yama göndereceğim.

[Güncelleme 22.05.2018] Bu davranışı düzeltmek için bir yama yazdım ve gönderdim .

[Güncelleme2 22.05.2018] Yama, yama seviyesi 8.1.0018 olarak birleştirildi

[Güncelleme 22.10.2019] Vim yaması 8.1.629'dan itibaren üçüncü adım artık yapılmamaktadır. Bunun yerine Vim artık maçın başlangıcını bulurken maçın sonunu belirleyebilir (Adım 2)


9

Christian, buggy davranışı sorununu tamamen ele aldı gn, ancak \zsve ile arasındaki temel farklılıklar hala var \@<=. En büyük varlık \@<=önceki atomu değiştirirken, \zskendi içinde bir atom.

Düşünmek:

Xnnoremap

\%1cX\zsnnoremap     (regex 1)
\%1cX\@<=nnoremap    (regex 2)
\%2cX\@<=nnoremap    (regex 3)

Regex 1 ile eşleşir, çünkü \%1csütun 1 ile eşleşir ve orada bir X vardır. \zsyalnızca maçın X'ten sonraki bir konumda yeniden başlatılmasına neden olur.

Bununla birlikte, Regex 2 eşleşmez, çünkü \%1cilk sütunla eşleşse de X\@<=sıfır genişliktir (belgelerde belirtildiği gibi) ve nnoremapsütun 2'de başlar. Sütun 1 ve 2 arasındaki konum farkını telafi edecek hiçbir şey yoktur.

nnoremapSütun 2'de başladığından bu yana normal 3 eşleşmesi .


1
Normal ifade 2 başarısız olduğunu sanmıyorum çünkü sütun 1 ve 2 arasındaki konum farkını telafi edecek bir şey yok. Sorun buysa nnoremap, normal ifadeden kaldırma bir eşleşme üretecektir; ama normal ifade hala olmadan da başarısız oluyor. Başarısız olduğunu düşünüyorum çünkü \%1cX\@<=var olmayan bir pozisyon ifade ediyor. \%1csütun 1'deki konumla eşleşir ve bundan önce X\@<=bir karakter Xeşleşmesini ister . Ancak ilk sütundan önce herhangi bir karakter olamaz. Bu nedenle, Xbir nokta (herhangi bir karakter) ile değiştirseniz bile normal ifade \%1c.\@<=yine de başarısız olur.
user938271

5

\zstüm normal ifadeye uygulanır ve sonraki karakteri tüm eşleşmenin ilk karakteri olarak ayarlar. Bundan önceki \zshiçbir şey eşleşen metnin bir parçası olarak dahil edilmez.

\@<=Öte yandan, sadece doğrudan etrafındaki atomları etkiler, bir sonraki atomun yalnızca önceki atomu takip etmesi durumunda eşleşeceğini belirtmenize izin verir. Örneğin, normal ifade:

\vbar.*(foo)@<=bar

İki örneğin bar(örneklerin kendileri dahil) arasındaki tüm metniyle eşleşir , ancak yalnızca ikincisi gelirse foo. yani, eşleşecektir:

barbazfoobar

Ama değil:

barbazbazbar

Çünkü \@<=bu şekilde lokalize olduğu, hatta kullanabilirsiniz \@<=Tek bir ifadede birden çok kez:

\vbar.*(foo)@<=bar.*(foo)@<=bar

Aşağıdaki üç örnekle eşleşir bar, ancak yalnızca ikincisinin öncesinde yer alırsa foo.

yani metin verildiğinde:

barfoobarbazfoobar
barfoobarbazbazbar
barbazbarbazfoobar

Yalnızca ilk satırla eşleşecektir.


Ama ilk olan ileriye dönük alışverişi yapabilir \zsyani, bu da çalışması gerekir: \vfoo\zsbar.*(foo)@<=bar.
Karl Yngve Lervåg

@ KarlYngveLervåg İyi bir nokta. Ayrımı daha net hale getirmek ve \zsikame edilemeyen örnekleri kullanmak için düzenledim .
Zengin

Yani, benim anlayışım için, \zsve \zeregex desenleri etrafına bakmak ile değiştirilebilir ve onlar daha güçlü, değil mi? Daha güçlü neden birden fazla kez kullanılabilir ve gruplandırılabilir \(\). Ve ayrıca perl'in regex etrafına bakması gibi çalıştıkları için. Yanlış bir şey var mı?
klaus

1
@klaus Kulağa doğru geliyor (uzman olmamama rağmen). Yine de, ne zaman yapabileceğinizi \zs/ kullanmanız gerektiğini unutmayın \ze, çünkü etrafa bakmaktan daha hızlıdır.
Zengin

Anladım. Ve \zsve \zeaçıkçası daha kolay anlaşılır. Açıklamalar için teşekkürler.
klaus
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.