İkinci satırdan başlayarak bir Vim tamponundan diğer her satırı silmek istiyorum, yani 2., 4., 6. satırlar, vb. Örneğin, tampon içeriği:
aaa
bbb
ccc
ddd
eee
fff
ardından, istenen hat kaldırıldıktan sonra şu hale gelmelidir:
aaa
ccc
eee
İkinci satırdan başlayarak bir Vim tamponundan diğer her satırı silmek istiyorum, yani 2., 4., 6. satırlar, vb. Örneğin, tampon içeriği:
aaa
bbb
ccc
ddd
eee
fff
ardından, istenen hat kaldırıldıktan sonra şu hale gelmelidir:
aaa
ccc
eee
Yanıtlar:
Bunun için bir makro kullanabilirsiniz. Aşağıdakileri yapın.
gg.qq.ddardından tuşuna basın .q.10000@qNot: Komut moduna gitmek için birkaç kez Escape tuşuna basın.
:g/^/+dstackoverflow.com/users/254635/ib adlı kullanıcıdan (aşağıda) bunu çözmenin daha şık bir yolu.
Görevi gerçekleştirmenin zarif (ve verimli) bir yolu, :+deletekomutu kullanarak her satırda mevcut satırı takip eden satırı kaldıran komutu çağırmaktır :global:
:g/^/+d
:1d|g/^/+dgarip satırları siliyor.
Verilen normal mod komutlarını çalıştırmak için :normalveya kullanabiliriz :norm. Kaynak.
:%norm jdd
%norm ddjTek satırları silmek istiyorsanız neden işe yaramadığıyla ilgileniyorum .
:map ^o ddj^o
^o
Burada ^ CTRL anlamına gelir. Her iki satırda bir satırı silmek için özyinelemeli makro. İlk satırınızı iyi seçin ve bitti.
dan vim posta arşive :
:let i=1 | while i <= line('$') | if (i % 2) | exe i . "delete" | endif | let i += 1 | endwhile
(Vim komut satırında bir satıra yazılacaksa, satır 1,3,5,7, ... silecektir.)
!perl -ne 'print unless $. % 2':-)
if (expression)Her üçüncü satır vb. İçin de işe yarayan esneklik nedeniyle +1
İstediğiniz herhangi bir komut dosyası dilini kullanabileceğiniz anlamına gelen bir kabuk komutundan her zaman geçiş yapabilirsiniz:
:%!perl -nle 'print if $. % 2'
(veya istediğiniz satıra bağlı olarak "eğer" yerine "sürece" kullanın)
-lPerl'e geçiş yapmanıza gerek yok ... Ayrıca, bunun Perl'den awkbiraz daha yaygın olduğunu söyleyebilirim , ancak bugünlerde o kadar da fazla değil ve bunu daha kısa yapabilir: :%!awk NR\%2veya :%!awk 1-NR\%2diğer satırlar için.
:%!awk -- '++c\%2'
alternatif olarak
:%!awk -- 'c++\%2'
hangi yarısını ayıklamak istediğinize bağlı olarak.
NRdeğişkeni kullanmıyorsunuz ?
:%!awk NR\%2veya :%!awk 1-NR\%2başka bir yorumda yayınladığım gibi. Bu pek uzun değil.
1-NRdaha uzun c++. Evet, bunun bir karakter olduğunu biliyorum. Dediğim gibi - gerçek sebep onu unutmuş olmam. Her neyse, görünüşe göre burada insanlar awk'ın güzelliğini takdir etmiyor.
NRdaha kısa ++c:)
Vim'in kendi arama ve ikame yeteneklerini şu şekilde kullanabilirsiniz: İmlecinizi ilk satıra getirin ve normal modda yazın:
:.,/fff/s/\n.*\(\n.*\)/\1/g
.,/fff/İkame ait aralıktır. "Bu satırdan normal ifadeyle eşleşen satıra fff(bu durumda son satır) anlamına gelir.s///yedek komuttur. Bir normal ifadeyi arar ve her geçtiği yeri bir dizeyle değiştirir. gUç vasıtası ile sürece normal ifade bulunan durduğu olarak ikame yineleyin.\n.*\(\n.*\)bir satırsonu ile, ardından tam bir satırla ( .*yeni satır dışında herhangi bir sayıda karakterle eşleşir), ardından başka bir satırsonu ve başka bir satırla eşleşir. Parantezler \(ve \)içlerindeki ifadenin kaydedilmesine neden olur, böylece daha sonra kullanabiliriz \1.\1 gruplanmış yeni satırı ve arkasından gelen satırı ekler, çünkü bir sonraki satırın da gitmesini istemiyoruz - sadece ikame mekanizmasının geçmesini istiyoruz, böylece bir sonraki değiştirmede silmeyiz.Bu şekilde, silme işleminin gerçekleşmesini istediğiniz aralığı kontrol edebilirsiniz ve herhangi bir harici araç kullanmak zorunda kalmazsınız.
$bunun yerine /fff/, dosyanın içeriğinden bağımsız olarak dosya sonu için.
Vim'inizin desteği varsa başka bir yaklaşım olarak python da kullanabilirsiniz.
:py import vim; cb = vim.current.buffer; b = cb[:]; cb[:] = b[::2]
b = cb[:]geçerli arabellekteki tüm satırları geçici olarak konumuna kopyalar b. b[::2]her ikinci satırı arabellekten alır ve tüm geçerli arabelleğe atar cb[:]. bArabellek nesneleri genişletilmiş dilim sözdizimini desteklemediğinden, to kopyalaması gereklidir.
Bu muhtemelen "vim yolu" değildir, ancak python'u biliyorsanız hatırlamak daha kolay olabilir.
Tek satırları silmek için (1,3,5, ..) -> :%s/\(.*\)\n\(.*\)\n/\2\r/g
Çift satırları silmek için (2,4,6, ..) -> :%s/\(.*\)\n.*\n/\1\r/g
Metni arayın (ilk satırı oluşturur), ardından yeni bir satır karakteri ve biraz daha metin (ikinci satırı oluşturur) ve ardından başka bir yeni satır karakteri gelir ve yukarıdakileri ilk eşleşme (tek satır) veya ikinci eşleşme (çift satır) ile değiştirin ve ardından satır başı.
bunu vim'de deneyebilirsin
:1,$-1g/^/+1d
Daha net olmaya çalışacağım (iki bölüm)
birinci bölüm seçim aralığı ( :from,to)
ikinci bölüm eylem ( dsil)
:1,$-1)g) +1dsonraki satırı ( ) silDosyanızın ilk satırına geçmeyi deneyebilir ve çalıştırabilirsiniz :+1d, sonraki satırın kaybolduğunu göreceksiniz
Biliyorum çamurlu, ama vim ve işe yarıyor