Vim'deki her iki satır nasıl silinir?


100

İ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

Bir makro kullanabilmeniz gerekir: oreillynet.com/mac/blog/2006/07/…
Mark Wilkins

Buna verilen cevapların zenginliğini seviyorum. Favorilere ekleniyor.
froggythefrog

Yanıtlar:


106

Bunun için bir makro kullanabilirsiniz. Aşağıdakileri yapın.

  • Komut modunda başlayın.
  • Düğmesine basarak dosyanın başlangıcına gidin gg.
  • Tuşuna basın qq.
  • Aşağı oku tıklayın ve ddardından tuşuna basın .
  • Tuşuna basın q.
  • Basın 10000@q

Not: Komut moduna gitmek için birkaç kez Escape tuşuna basın.


11
Dosyanızın 20.000 satırdan daha az olduğunu varsayarsak elbette :-)
paxdiablo

3
Aslında yanılıyorsun Michael. VI dosyanın sonuna ulaşır ulaşmaz makroyu çalıştırmayı durduracağı için bu kusursuz çalışır. Yukarıdaki örnekle çok kolay bir şekilde deneyebilirsiniz.
rui

1
Pekala, tıpkı herhangi bir makro gibi, ilk seferde doğru yapmanız gerekir, ancak bundan sonra herhangi bir dosyaya sadece 10000 @ q yazarak başvurabilirsiniz. Her iki durumda da bunun sadece bir zevk meselesi olduğuna inanıyorum, bu yüzden kesinlikle felsefi bir tartışma başlatmayacağım. :)
rui

3
'Makro' kullanmayı tercih ederim. Makro kullanarak, belirli bir görevi nasıl çözeceğinizi 'tanımlarsınız' ve VIM'in sizin için tekrar etmesine izin verirsiniz. RUI, ok tuşu yerine 'j' kullanmayı tercih ederim.
SolutionYogi

4
:g/^/+dstackoverflow.com/users/254635/ib adlı kullanıcıdan (aşağıda) bunu çözmenin daha şık bir yolu.
SergioAraujo

260

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

10
Bu yanıt neden daha fazla olumlu oy almadı? Bu çok temiz ve basit. Alternatif olarak, tüm tek satırları silmek için ilk satırı silebilir ve yukarıdaki komutu çalıştırabilirsiniz.
Usagi

3
@Usagi: Teşekkür ederim! Ben de aynı şekilde hissediyorum. Ve evet, kesinlikle haklısın, :1d|g/^/+dgarip satırları siliyor.
ib.

3
Üzgünüm, ancak bu komutun istenen davranışı nasıl gerçekleştirdiğine dair bir açıklama olmasaydı, onu desteklemeyeceğim ve bunun yerine kabul edilen cevabı tercih ediyorum, çünkü amaca nasıl ulaştığını anlıyorum. Bir adama balık vermekle ona balık tutmayı öğretmek arasındaki fark bu.
Gabe

3
Bilmiyorum, bu cevap dışarı çıkıp: g komutuyla balık tutmayı öğrenmemi sağladı (yani, beni bu sayfayı google'da - vim.wikia.com/wiki/Power_of_g yaptı ).
2014

1
Ve ona bir balıkla vurursan ... Ama hey, kabul edilen cevap da açıklamıyor. Global komut belgesini yeniden oluşturmanın bir anlamı yok. Küresel komutun nasıl kullanılacağını unutmuştum (eski bir vi kişisi olmasına rağmen) ve bu sayfayı Google'da buldum. Çok yardımcı.
Isaac Rabinovitch

66

Verilen normal mod komutlarını çalıştırmak için :normalveya kullanabiliriz :norm. Kaynak.

:%norm jdd

15
Bu cevap, muhtemelen hem burada hem de bağlantılı, dağınık, kopya kağıdındaki açıklama eksikliğinden dolayı yeterince dikkat çekmiyor. norm komutu, onu takip eden harflere eşdeğer normal mod komutlarını çalıştırır. Yani burada bir satır aşağı gitmek için j ve onu silmek için dd çalışıyor. Bu, bu durumda daha fazla 'j' ekleyerek X'inci satıra genellenebilir.
imoatama

5
ve% 1, $ için kısaltmadır (aşağıdaki komutu 1. satırdan sonuna kadar
yürütün

3
%norm ddjTek satırları silmek istiyorsanız neden işe yaramadığıyla ilgileniyorum .
Cyker

10
: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.


8

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.)


4
O halde !perl -ne 'print unless $. % 2':-)
Alex Brasetvik

Ve Alex, kesinlikle kendi çözümümü seninkine tercih ederim, ama bu dikkate değer çünkü burada sadece vim kullanan tek mantıklı çözüm bu.
Michael Krelin - hacker

Makro yol çok daha kolay.
trusktr

if (expression)Her üçüncü satır vb. İçin de işe yarayan esneklik nedeniyle +1
Jens

5

İ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.
ephemient

4
:%!awk -- '++c\%2'

alternatif olarak

:%!awk -- 'c++\%2'

hangi yarısını ayıklamak istediğinize bağlı olarak.


Umm, neden mevcut NRdeğişkeni kullanmıyorsunuz ?
süreli

Sağ. Çünkü unutmuşum. ;-) Ama aslında, "uygun" değişken, NR ile daha da uzun olacaktır. Ve iki güzel görünümlü muadili olmayacaktı .
Michael Krelin - hacker

:%!awk NR\%2veya :%!awk 1-NR\%2başka bir yorumda yayınladığım gibi. Bu pek uzun değil.
süreli

1
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.
Michael Krelin - hacker

Ve NRdaha kısa ++c:)
efemient

3

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.
  • Normal ifade \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.


Veya $bunun yerine /fff/, dosyanın içeriğinden bağımsız olarak dosya sonu için.
süreli

3

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.


2

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şı.


0

Sed'i çağırın:

:% !sed -e '2~2 d'

^^^^                  pipe file through a shell command
    ^^^^^^            the command is sed, and -e describes an expression as parameter
            ^^^^^     starting with the second line, delete every second line

-1

çözüm

bunu vim'de deneyebilirsin

:1,$-1g/^/+1d

Düzenle

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)

  • ilk satırdan son satıra kadar olan aralık, ancak bir satır ( :1,$-1)
  • globaly ( g) +1dsonraki satırı ( ) sil

Dosyanı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


Çamur kadar temiz. Teşekkürler!
Henry Henrinson
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.