Https://vi.stackexchange.com/a/818/227 adresindeki cevaba benzer şekilde global komutu kullanabilirsiniz.
Bununla birlikte, vim'e bir modelle eşleşen satırları aramasını ve ardından komutları gerçekleştirmesini söyleyebilirsiniz.
Sizin durumunuzda, "Seviye N:" ile başlayan satırlara metin eklemek istersiniz, böylece global komutumuz
:g/^Level \d:/{COMMANDS}
Komut için substitute komutunu (normal ifade değiştirme) kullanma
Komutlar daha eğlenceli. Değişkenleri kullanmak kolay olduğu için genellikle böyle şeyler için düzenli bir ifade değişikliği yapmak isterim.
Sorunuz için örnek
:let i = 1 | g/^Level \d:/s/^/\=printf("%02d ", i)/ | let i = i+1
Nasıl çalışır
İkame komutunun değiştirme bölümünde bir ifade olabilir.
Yapacağımız ilk şey i
, başlangıç değişkeni olarak bir değişken ayarlamaktır . 1'i seçtim, ancak herhangi bir sayı yapacak.let i = 1
Ardından, eşleşen satırlarda bir eylemde bulunmamızı sağlayan global komutumuzu çalıştırıyoruz. g/^Level \d:/
Global komutumuzun değeri girmesini ve substitüsyon komutunu ve let komutunu kullanarak sayacımızı artırmasını sağlayacağız.s/^/\=printf("%02d ", i)/ | let i = i+1
Değiştirme komutunun normal ifadesi satırın başlangıcını bulur ve ^
bir ifadeyle değiştirir ve ifademiz biçimlendirilmiş bir baskının sonucu olacaktır. C dilinde olduğu gibi, vim'in printf formatlama parametrelerini alır. %02d
"" ifadesi, bir argümanı ondalık sayı gibi dönüştürmek d
, en az 2 boşluk 2
ve 0 ile doldurmak anlamına gelir 0
. Ayrıntılar ve diğer dönüştürme seçenekleri (kayan nokta biçimlendirme dahil) için bkz :help printf
. Printf'e sayım değişkenimizi veriyoruz i
ve bu bize 01
ilk kez, 02
ikinci kez vb.
Ben d: sonra bir boşluk koymak unutmayın "%02d "
. Bunu soruda sormadınız (ve örnek çıktı görmedim), ancak sayıyı "Seviye" kelimesinden ayırmak istediğinizden şüphelendim. Girilen sayının Seviye L'nin hemen yanında olması için printf'ye verilen dizeden boşluğu kaldırın.
Son olarak, bu let i = i + 1
her değişiklikten sonra sayacımızı arttırır.
Bu genellikle, diğer ölçütlerle eşleşen satır bölümlerini rastgele işlevsel verilerle değiştirmek için uygulanabilir.
Birleşik normal komutları kullanma
Bu, basit eklemeler veya karmaşık düzenleme için iyidir. Yerine koymada olduğu gibi, eşleşmek için global'i kullanacağız, ancak normal ifade yerine koymak yerine, kullanıcı tarafından yazılmış gibi bir dizi işlem gerçekleştireceğiz.
Sorunuz için örnek
:let i = 1 | g/^Level \d:/execute "normal! I" . printf("%02d ", i) | let i = i+1
Nasıl çalışır
Kullanılan değerler ikame değere çok benziyor (hala 2 rakamla dolgulu hale getirmek için sayımızı biçimlendirmek için printf kullanıyoruz), ancak işlem farklı.
Burada bir dizeyi alan ve dizeyi ex komutu ( :help :exe
) olarak çalıştıran execute komutunu kullanıyoruz . Verilerimizle "normal! I" i ilk kez "normal! I01" ve ikinci kez "normal! I02" olacak şekilde birleştiren bir dize oluşturuyoruz.
normal
Komut gerçekleştirdiği operasyonlar normal modda sanki. Bu örnekte, normal komutumuz I
satırın başına eklenir. Eğer dd
kullansaydık çizgiyi siler o
, eşleşen çizgiden sonra yeni bir çizgi açardı. Sanki I
normal modda yazdınız (veya başka bir işlem yapıyorsunuz ). Kullandığımız !
SONRA normal
emin hiçbir eşleştirmeleri yolumuza olsun yapmak. Bkz :help :normal
.
O zaman eklenen ilk örnekte olduğu gibi printf değerimizdir.
Bu yöntem regex'ten daha meraklı olabilir, çünkü execute "normal! ^2wy" . i . "th$p"
metnin başına gidecek ^
, 2 kelime ileri gidecek 2w
, '' h 'karakterine kadar çekilecek y" . i . "th
, satırın sonuna $
gidip yapıştıracak gibi şeyler yapabilirsiniz p
.
Bu neredeyse bir makro çalıştırmak gibidir, ancak aslında bir kayıt kullanmaz ve herhangi bir ifadeden dizeleri birleştirebilir. Bunu çok güçlü buluyorum.
Her seviyenin kendi sayacı olduğu yaklaşım
Her seviyenin kendi sayacını almasını isteyebilirsiniz. Önceden maksimum seviye sayısını biliyorsanız, aşağıdakileri yapabilirsiniz (en büyük seviyeyi bulmak için ekstra kod eklemek çok zor olmayabilir, ancak bu cevabı çok uzun sürebilir.
İlk olarak, zaten bir tamsayı olarak kullanmış olursak, i serbest bırakalım. İ'yi bir listeye dönüştüremeyiz, onu bu şekilde yaratmalıyız.
:unlet! i
Daha sonra, i'yi seviye sayısını içeren bir liste olarak ayarlayalım. Sorunuzda 2 tane gösterdiniz, ancak eğlenmek için 10 olduğunu varsayalım. Liste indeksleme 0 tabanlı olduğundan ve listeniz gibi 1 için düzeltme yapmak istemiyorum, sadece yeterli elemanlar (11) oluşturacağız ve asla 0 indeksini kullanmayacağız.
:let j = 0
:let i = []
:while j < 11 | let i += [1] | let j += 1 | endwhile
Sonra, seviye numarasını almak için bir yola ihtiyacımız var. Neyse ki, ikame de bir işlev olarak mevcuttur, bu yüzden ona satırımızı vereceğiz ve seviye numarasını çıkaracağızsubstitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")
İ artık 11 1
saniyelik bir liste olduğundan (her bir dizin seviyemiz için sayaçtır), şimdi bu değiştirmenin sonucunu kullanmak için yukarıdaki örneklerden birini ayarlayabiliriz:
Yedek komut ile:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | s/^/\=printf("%02d ", i[ind])/ | let i[ind] += 1
Normal komut ile:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | execute "normal! I" . printf("%02d ", i[ind]) | let i[ind] += 1
Örnek girdi:
Level 1: stuff
Level 1: Stuff
Some text
Level 3: Other
Level 1: Meh
Level 2: More
Örnek çıktı:
01 Level 1: stuff
02 Level 1: Stuff
Some text
01 Level 3: Other
03 Level 1: Meh
01 Level 2: More