Bir devletle yer değiştirmeye ihtiyacınız var. SO bu tür sorunlar için (/ birkaç?) Tam bir çözüm sağladığını hatırlıyorum .
İşte ilerlemenin başka bir yolu (1). Şimdi 2 adıma geçeceğim:
- kullanacağım kirli ve kıvrımlı numara için ihtiyacım olan bir kukla liste değişkeni
- her bir eşleme olayı dolduruyorum ben bu kukla dizinin len eklemek bir ikame.
Hangi verir:
:let t=[]
:%s/#\zs\d\+\(\.\d\+\)\=\ze/\=len(add(t,1))/g
Normal ifadeleri vimlemeye alışkın değilseniz, hangi alt kalıbı eşleştirdiğimi belirtmek için kullanıyorum :h /\zs
ve \ze
sonra bir nokta ve diğer rakamlarla izlenen bir dizi rakamla eşleşiyorum. Bu herhangi bir kayan nokta sayısı için mükemmel değildir, ancak burada yeterlidir.
Not: Basit bir arayüz için bir çift işlev + komutuna sarmanız gerekir. Yine, SO / vim üzerinde örnekler var ( burada , burada , burada ) Bugünlerde bu hileyi bir komuta sarmayı umursamayacak kadar vim biliyorum. Gerçekten de ilk denemede bu komutu yazabiliyorum, komutun adını hatırlamak birkaç dakika sürecek.
(1) Amaç, ikameler arasındaki bir durumu koruyabilmeyi ve mevcut olayı mevcut duruma bağlı bir şeyle değiştirebilmektir.
Bu sayede :s\=
bir hesaplamadan kaynaklanan bir şey ekleyebiliyoruz.
Devlet sorununu ortadan kaldırır. Harici bir durumu yöneten bir fonksiyon tanımlarız veya kendimizi harici bir durumu güncelleriz. C dilinde (ve ilgili dillerde), length++
veya gibi bir şey kullanabilirdik length+=1
. Ne yazık ki, vim komut dosyalarında, +=
kutunun dışında kullanılamaz. İle :set
veya ile birlikte kullanılması gerekir :let
. Bu, :let length+=1
bir sayıyı artırır ancak hiçbir şey döndürmez. Yazamayız :s/pattern/\=(length+=1)
. Başka bir şeye ihtiyacımız var.
Değişen işlevlere ihtiyacımız var. yani girdilerini değiştiren işlevler. Biz setreg()
, map()
, add()
muhtemelen daha. Onlarla başlayalım.
setreg()
bir kaydı değiştirir. Mükemmel. setreg('a',@a+1)
@Doktor OSwaldo'nun çözümünde olduğu gibi yazabiliriz . Ve yine de, bu yeterli değil. setreg()
bir fonksiyondan çok bir prosedürdür (Pascal, Ada'yı bilenler için). Bu, hiçbir şey döndürmediği anlamına gelir. Aslında, bir şey döndürüyor. Nominal çıkış ( istisna dışı çıkışlar) her zaman bir şeyler döndürür. Varsayılan olarak, bir şeyi iade etmeyi unuttuğumuzda, 0 döndürülür - yerleşik işlevlerle de uygulanır. Bu yüzden çözümünde yerine koyma ifadesi aslında \=@a+setreg(...)
. Zor, değil mi?
map()
de kullanılabilir. Bir listeden tek bir 0 ( :let single_length=[0]
) ile başlasak, sayesinde artırabiliriz map(single_length, 'v:val + 1')
. O zaman yeni uzunluğu iade etmeliyiz. Bunun aksine setreg()
, map()
mutasyona uğramış girdisini döndürür. Bu mükemmel, uzunluk listenin ilk (ve benzersiz ve dolayısıyla da son) konumunda saklanır. Değiştirme ifadesi olabilir \=map(...)[0]
.
add()
alışkanlıktan sık sık kullandığım şey ( map()
aslında hakkında konuştum ve henüz kendi performanslarını test etmedim). Buradaki fikir, add()
bir listeyi geçerli durum olarak kullanmak ve her bir değişiklikten önce sonuna bir şey eklemektir. Yeni değeri genellikle listenin sonunda saklarım ve değiştirme için kullanırım. Gibi add()
aynı zamanda mutasyona uğramış giriş listesini döndürür, biz kullanabilirsiniz: \=add(state, Func(state[-1], submatch(0)))[-1]
. OP durumunda, şu ana kadar kaç eşleşme tespit edildiğini hatırlamamız gerekiyor. Bu durum listesinin uzunluğunu döndürmek yeterlidir. Dolayısıyla benim \=len(add(state, whatever))
.
perldo
, kullanabilirsiniz:%perldo s/#\K\d+(\.\d+)?/++$i/ge