Her 4 satırda nasıl tersine dönülür?


13

Her şeyden önce, bu benim ilk yazım olmakla birlikte, VIM'in harika bir araç bulduğumu ve buradaki forumun sorulara cevap bulmada çok yardımcı olduğunu bulduğumu söylemek istiyorum. paha biçilmez yardım. VIM için hala çok yeniyim, bu yüzden öğrendiğim her şey buradan geldi.

Benim sorum: Bir dosyadaki TÜM satırları tersine çevirmeyi biliyorum (: diğer yolların yanı sıra g / ^ / m0), ancak bir dosyadaki her 4 satırı tersine çevirmenin bir yolu var, böylece

line1
line2
line3
line4
line5
line6
line7
line8
...

olur

line4
line3
line2
line1
line8
line7
line6
line5
...

Bu tür dosyalarda her zaman 4 satırın tam bir katı olacağını varsayabilirsiniz.


2
"Ps" iniz hakkında: bir satırın önüne 4 boşluk eklerseniz, kod olarak yorumlanır (metni seçebilir ve üstteki biçim düğmelerini kullanabilirsiniz). Üstteki sorgulama simgesiyle ilgili daha fazla ayrıntı bulabilirsiniz .
mMontu

Yanıtlar:


15

Vim Wiki'de:Reverse açıklanan komut bunun için kullanılabilir ( kalıcı yapmak için içine ekleyebilirsiniz):.vimrc

command! -bar -range=% Reverse <line1>,<line2>g/^/m<line1>-1|nohl

Ardından, komutu her dört satırda çalıştırmak için bir makro kaydedebilirsiniz:

qmV3j:Reverse<cr>4jq
1000@m

Açıklama:

  • qm: 'q' normal modda belirli bir kayıtta bir makro kaydetmeye başlar (ve durur) (bu durumda 'm' kaydedin, ancak başka bir harf olabilir)
  • V: görsel moda gir ve geçerli satırı seç
  • 3j: görsel seçimi sonraki 3 satıra genişlet
  • :Reverse<cr>: Seçilen satırlarda Reverse komutunu çalıştırın ( <cr>burada enteranahtar kısaltmasıdır )
  • 4j: değişmeyen bir sonraki satıra git
  • q: makro kaydını durdurur
  • 1000@m: 'm' kaydında kaydedilen makroyu 1000 kez çalıştırın (dosyanız 4000 satırdan büyükse bu sayıyı artırabilirsiniz)

Düzenle:

Yorumlarda belirtildiği gibi, sayı kullanmak yerine özyinelemeli bir makro kullanabilirsiniz:

qmV3j:Reverse<cr>4jq
qM@mq
@m
  • qM: için belirtilen kayıt qbüyük harfse, makro kayda eklenir (karmaşık bir makronun son adımlarını kaçırdığınızı fark ettiğinizde de yararlıdır)
  • @m: makroyu kayıtta çalıştır m
  • q: makroyu eklemeyi bırak

Makro olarak oluşturulmasına rağmen, iş akışınızda ortak bir görevse bunun için bir komut oluşturabilirsiniz:

function! Reverse4()
   let reg_m = @m
   let @m = '<c-r><c-r>m'
   normal! @m
   let @m = reg_m
endfunction
command! Reverse4 call Reverse4()
  • function! Reverse4()/ endfunction: yeni bir işlev tanımlar
  • let reg_m = @m: kaydın mevcut içeriğini kaydeder m
  • let @m = "<c-r><c-r>m": Kayıt içinde makro insert m- not <c-r>için vim notasyonu olan Ctrl+ rve gerektiği yazın satır benzer olacaktır, böylece bu, kopyala / yapıştır değil let @m = 'V3j:Reverse^M4j@m've bir içerecektir özel karakter (^ M)
  • normal! @m: normal komut argümanını normal modda yazıldığı gibi çalıştırır, böylece özyinelemeli makroyu çalıştırır
  • let @m = reg_m: kaydın içindekileri geri yükler m, bu nedenle bu kaydın bu işlevde kullanıldığını hatırlamak ve kullanmaktan kaçınmak zorunda değilsiniz

  • command! Reverse4 call Reverse4(): bu işlev için yeni bir komut oluştur

İhtiyaçlarınıza bağlı olarak onu geliştirebilirsiniz, örneğin: Komut ve işleve bir argüman iletin, böylece 4 satırlık gruplar halinde sabitlenmek yerine herhangi bir sayıda satır için çalışır.


Yerine 1000@qhack, ayrıca bir özyinelemeli makro kullanabilirsiniz: qmqqm ... @mq@m.
Kapı tokmağı

"QmV3j: Ters <cr> 4jq" çalıştırmayı denediğimde, "E492: bir editör komutu değil" dedi. Yanlış bir şey yapmalıyım. Bu arada GVIM kullanıyorum - ve daha önce hiç kullanmadım. İlk etapta bundan bahsetmeliydim.
ablewasiereisawelba

Ah boşver. Anladım - "qmV3j: Ters <cr> 4jq" bölümünden önce ":" yazmam gerekiyordu. İşe yaradı! Çok teşekkürler mMontu. Eğer sorabilirsem - .vimrc'ye ": Reverse" komutunu nasıl ekleyebilirim?
ablewasiereisawelba

3
@ablewasiereisawelba Komutun kalıcı olarak kullanılabilir olmasını sağlamak için satırı vimrc'nizde bir command! -bar -range=% Reverse <line1>,<line2>g/^/m<line1>-1|nohlyere yazmanız yeterlidir .
saginaw

@saginaw Oh, bunun bu kadar basit olduğunu fark etmedim. Teşekkür ederim.
ablewasiereisawelba

9

Olduğu gibi tüm tekrarlanan eylemler , daha sonra kolayca bir makro kaydederek çok defalar çok yapabilirim, temel düzenleme işlemleri ile bir şeyler kez yapabilirim.

(Bu durumda özyinelemeli bir makro kullanacağım, ancak özyinelemesiz bir makro kaydedebilir ve çekiçle @@veya bir sayı kullanarak birden çok kez oynatabilirsiniz .)

ggqqqqqddjjpkddkkPjddpjj@qq@q

Bozuldu

  1. gg: Dosyanın başına gitme.
  2. qqq: Kayıt defterini temizle q. Bunun 5. adımda neden gerekli olduğunu göreceğiz.
  3. qq: Q kaydetmek için makro kaydetmeye başlayın
  4. ddjjpkddkkPjddpjj: İlk dört satırı, bunları manuel olarak silerek ve yapıştırarak yeniden sıralayan bir dizi işlem. (Bu ilk bakışta karmaşık görünebilir ama aldatılmak değil Bu ilk 5 dakika içinde öğrenmiş ya olurdu çok basit şeyler yani evi. vimtutor: j, k, dd, p, P)
  5. @q: Makroyu ara! Bu noktada, kayıt qhiçbir şey içermez (çünkü 2. adımda temizledik), bu yüzden hiçbir şey olmayacak.
  6. q: Makroyu kaydetmeyi durdurun.
  7. @q: Özyinelemeli makroyu gerektiği kadar tekrarlayın.

Not Dosya dört ile bölünemeyen bir dizi satır içeriyorsa, yukarıdakiler istenen sonuçları vermeyecektir. Dört satır kalmadıysa makroyu erken durdurmak için, 4. adımdaki düzenlemeleri uygulamaya başlamadan önce başarısız olacak bir Vim normal mod komutunu uygulamalıyız. çizgileri hareket ettirmeye başlamadan önce üç kez bir çizgi (ve sonra yedekleyin):jjj3k

Böylece:

ggqqqqqjjj3kddjjpkddkkPjddpjj@qq@q

Q kaydını neden açıkça temizliyorsunuz? Sadece içine kayıt yaparsanız, orada ne varsa zaten üzerine yazılır ....
Wildcard

4
@Wildcard Özyinelemeli bir makro olduğundan, kayıt içeriğini ilk kez çağırdığınızda qboş olması gerekir, aksi takdirde sürümlerinizi bozar.
saginaw

Çok hoş. Komutunuzun tam sırasını qqqggqqjjjkddkkPjddjpkddkkPjjjj@qq@q
Wildcard

1
@ablewasiereisawelba where I can just use the one-line custom command each time I need to do this- vimrc'nizde bir işlev / komut olarak saklamak mümkün olduğundan, makroyu her kullanmanız gerektiğinde yeniden oluşturmanız gerekmediğini unutmayın.
mMontu

1
@ablewasiereisawelba "Düzenle" yi yararlı bulduğunuza sevindim! Buradaki ilk yazınız olduğu için belki StackExchange bildirimlerinin nasıl çalıştığının farkında değilsiniz: bir yorum yayınladığınızda, cevap / soruların yazarı bir bildirim alır; diğer kişilere yalnızca @ <nick> eklerseniz bir bildirim gönderilir. Böylece yalnızca Rich son iletileriniz hakkında bildirim aldı.
mMontu

7

Bunu harici filtre olarak Exkullanarak bir komutla da yapabilirsiniz sed:

:%!sed -n 'h;n;G;h;n;G;h;n;G;p'

Bu sürüm, 4'ün katlarının ötesindeki fazladan satırları yok sayar (siler). 4 satırdan az (ters) son kümede tutmak için şunu kullanın:

:%!sed -n '$p;h;n;G;$p;h;n;G;$p;h;n;G;p'

%Burada "tampon her satırını" anlamına gelir.

!Komut aracı "girdi olarak belirtilen hatlar ile aşağıdaki komutu çalıştırın ve yerine komutun çıkış belirtilen hatlar." (Buna filtre denir; sıralama gibi şeyler için çok kullanışlıdır, örneğin, :%!sortdosyanızdaki tüm satırları sıralar; :2,8!sort2-8 satırlarını sıralar vb.)

sedolan dere editörü aracı ve tüm Unix benzeri sistemlerde bulunur. Anahtar kavramlar sedburada kullanılan kullanırken ekstra metin sopa nerede olduğu ((varsayılan olarak sadece sırayla girişin her satırı içerir) "desen alanı" ve "tutma alanı" olan seddiğer işlerken kaydetmek için giriş satırları).

-nsedkomutunun, desen alanını yazdırma varsayılan eylemlerini bastırmak için bir seçenektir (çünkü bu durumda yalnızca açıkça söylediğimizde yazdırmak istiyoruz.)

$piçinde sed"sen son satırında ise komut vasıtası sedbireyin girdi, baskı (desen boşluk)".

h "mevcut alanın üzerine yazarak" desen alanı "nın mevcut içeriğini" tutma alanı "na yapıştırın."

n "desen alanı" nın içeriğini girişten sonraki satırla değiştir. "

G "örüntü alanına" ekle: bir satırsonu ve ardından hold tutma alanı’nın içeriği. "

Hepsi birlikte ele alındığında, sedkomut dört çıktı satırı depolar, bunları depolarken tersine çevirir ve sonra yazdırır. $pİkinci versiyonda ilave komutları dosyanın en son satır 4 hatlık bir çoklu dışında başka ulaşılırsa, satır yine basılır emin olun.


Vim'e özgü özellikler kullanmadan ve harici filtre kullanmadan alternatif, etkileşimli bir yaklaşım için:

:4

dördüncü satıra gitmek için.

:.m -4 | +3m . | +2m . | +5

önceki dört satırı (1-4) tersine çevirin ve imlecinizi 8. satırda bırakın.

.m -4Sadece mevcut çizgisini taşır sonra (taşınan satırda imleci bırakarak) dördüncü hatta hatları geri.

+3m .imleci taşınan satırda bırakarak, geçerli satırdan sonraki 3 satır olan satırı geçerli satırın hemen sonrasına taşır . +2m .Tabii ki aynı şekilde çalışıyor.

+5 imleci bulunduğu yerden beş satır aşağıya yerleştirir.

İstediğiniz şekilde tekrarlayın.

Vim'de bu komutun tamamını ile @:tekrarlayabilir, ardından ile tekrarlayabilirsiniz @@. POSIX'deki viveya exsize gerekir insert :.m -4 | +3m . | +2m . | +5 , metin satırı olarak adlandırılmış tampon (register) için silin ve ardından bu adlandırılmış tampon (register) yürütün.

Bu nedenle, exmodda, satırları yalnızca POSIX tarafından belirtilen özellikleri kullanarak etkileşimli olarak tersine çevirme ve 17 metin satırından başlayarak:

Entering Ex mode.  Type "visual" to go to Normal mode.
:0a     # Append following text after "line 0" (i.e. insert at start of file).
.m -4 | +3m . | +2m . | +5
.       # End text insertion
:d k    # Delete that line to register k
line1   # This is a printout of the current line
:4      # Move to line 4
line4
:@k     # Execute register k to reverse lines 1-4
line8
:@@     # Execute register k again
line12
:@@     # Execute register k again
line16
:@@     # Execute register k again
line17
:%p     # Print the whole buffer (just to see what was done)
line4
line3
line2
line1
line8
line7
line6
line5
line12
line11
line10
line9
line16
line15
line14
line13
line17
:wq     # Save and quit

Daha fazla okuma:


Çözümünüzü biraz daha açıklayabilir misiniz?
vappolinario

3
@vappolinario, biraz daha açıklama ekledim. Bu yardımcı olur mu? :)
Wildcard

Vay, çok uzun cevap. :) Aslında sed var, ama ben sadece bir yerde buldum basit bir komut dosyası ile kullandım - muhtemelen bu tahtada - bu bir sorun için bir çözüm oldu. Ancak, önerilen satırınızı çalıştırmayı denediğimde, "sed" dahili veya harici bir komut, çalıştırılabilir program veya toplu iş dosyası olarak tanınmadı. Vim klasöründe sed olması gerekip gerekmediğinden emin değilim.
ablewasiereisawelba

1
@ablewasiereisawelba, bir Windows kutusunda çalışıyorsanız ve Cygwin (veya MobaXterm veya benzeri) kullanmıyorsanız, verdiğim diğer yöntemi deneyebilirsiniz: 4G:.m -4 | +3m . | +2m . | +5<Enter>@:daha sonra @@dosyanız tamamen işlenene kadar tekrarlayın. Yine de MobaXterm'i yüklemenizi tavsiye ederim. :)
Wildcard

@Wildcard Oh tamam, şimdi MobaXterm'i kontrol ediyorum. :)
ablewasiereisawelba

7
:g/^/exe 'm .-' . substitute(line('.') % 4, '^0$', '4', '')

Düz İngilizce: Her satırda, mevcut çizgisini yukarı taşımak lnum % 4sürece, lnum % 4 == 0bu durumda geçerli satırı yukarı taşımak, 4.

Ayrıca, her nsatırı tersine çevirmek 4için yukarıdaki komuttaki 'leri değiştirin n.


2
Çok güzel bir satırlık komut. Teşekkürler djjcast.
ablewasiereisawelba
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.