Satırların sırasını nasıl tersine çevirebilirim?


24

Satırların sırasını nasıl değiştirebilirim, böylece ilk satır sonunda görünür ve son satır önce görünür? (Tampondaki tüm satırlar, adres aralıkları veya doğrusal görsel mod seçimi olabilir.)

Dönüştürmek istiyorum

rat
ox
tiger
⋮
dog
pig

içine

pig
dog
⋮
tiger
ox
rat

gibi harici bir komuta başvurmadan tac.


Bu soru hakkında daha iyi etiketler için herhangi bir öneriniz var mı?
200_success

1
belki yeni bir 'saf-vi' veya benzeri bir etiket? Hiçbir harici araca sahip olma isteğini belirten bir etiketten fayda sağlayacak birkaç soru gördüm. Bunu Meta hakkında mı sormalıyım?
John O'M.

1
@Carpetsmoker (ve bunu takip etmek isteyen başka biri) etiket sorusu artık meta meta.vi.stackexchange.com/questions/1229/… adresinde
John O'M.

Yanıtlar:


29

Globalin gücü burada işe yarayacak:

:g/^/exe "normal ddggP"

Veya daha basit (teşekkürler @tommcdo)

:g/^/move 0

İlki, her satırla eşleşecek ve her satır için onu silip dosyanın üstüne yapıştırın. Dosya içinde hareket ettikçe metni tersine çevirir.

İkincisi benzer şekilde her satıra eşleşir ve dosyayı dosyanın üstüne taşır.

Not: Bunların her ikisi de tüm dosya üzerinde çalışır ve satırların bir alt kümesini tersine çevirmek için doğru olarak uygulanmaz. Menzil içinde çalışan bir çözüm için Ingo Karkat'ın cevabına bakınız .

Açıklama:

ggenel komut
/^/bir başlangıcı (yani tüm hatlar) olan herhangi bir satırla aynı
exeaşağıdaki dizeyi yürütmek
"normalnormal mod komutları gerçekleştirmek
ddsilme hat
ggdosya üstüne hamle
Pmevcut konumda yukarıda macun

move 0 Geçerli satırı, 0 satırının altına taşır (bu, 1 konumuna veya dosyanın ilk satırına yerleştirir)


6
:normalKomut yerine :move 0, satırı arabelleğin başlangıcına taşıyan Ex komutunu kullanabiliriz .
tommcdo

1
Ayrıca :executeyalnızca komutun dinamik olarak oluşturulması gerektiğinde de gereklidir, örn :execute 'normal' g:user_command.
tommcdo

@tommcdo iyi puan! Kullanma alışkanlığım var, :executeçünkü daha sonra mevcut :exeolandan sonra başka Ex komutları eklemeyi bırakıyorum ve oraya geri dönüp daha sonra eklemek zorunda kalmamdan daha kolayım. Ne yazık ki, bu alışkanlık bu cevaba sızdıramadı.
John O'M.

1
Kullanımım hakkında daha fazla açıklama :execute: Bir dize aldığından, normal mod komutlarının bittiği yer için net bir açıklama sağlar, dize oluşturmama rağmen, dengeli tırnak işaretleri bulmak benim için aramaktan daha kolaydır. <esc>ya da modu sonlandırmak için ne gerekiyorsa. Yine, bu kişisel tercih ve alışkanlıktır. :-)
John O'M.

3
Bu btw aralığında çalışacaktır: :9,11g/^/move 8... Son sayının eksi 1 aralığının başlangıcı olması gerekir (Ingo'nun cevabından uyarlanmıştır).
Martin Tournoij

13

Bu bir astar (sizin için ~/.vimrc) bir :Reversekomut tanımlar ; :globaldoğrudan parçayı da kullanabilirsiniz , ancak :move(yinelemeli olarak aralığın başlangıcından önce satırlara kayması, dolayısıyla tersine çevrilmesi) sözdiziminin hafızaya alınması kolay değildir:

:command! -bar -range=% Reverse <line1>,<line2>global/^/m<line1>-1

1
Okuyucular için bir FYI olarak, <line1>& <line2>bu çalışmayı bir aralıkta yapmak zorundadır, yani: :7,9Reverse(özellikleri ya da commanddeğildir ). Daha basit globalmove:command! -bar -range=% Reverse :global/^/m 0
olanı

6

Saf Vim:

:g/^/m0

Açıklama:

Göre :help multi-repeat, :gve onun kuzeni :viki taramalı şekilde çalışır.

İlk :gsatırda her satırın eşleştiğini işaret {pattern}ederken, ikinci satırda (görünüşte dosyanın başlangıcında başlayıp sonuna kadar devam eder) gerçekleştirir [cmd]. Yukarıdaki kullanım :g, hatların işlendiği sıradan faydalanır (muhtemelen teknik olarak garanti edilmese de muhtemelen tamamdır).

Önce her satırı işaretleyerek, sonra ilk işaretli çizgiyi dosyanın üstüne getirip, ardından ikinciyi dosyanın üstüne (daha önce taşınan çizginin üstünde), ardından üçüncü işaretli çizgiyi (daha önce taşınan çizginin üstünde) hareket ettirerek çalışır. satır), ve böylece dosyadaki son satır yukarı taşana kadar etkin bir şekilde tersine çevrilir.

:gİşlenen satırların yukarıdan aşağıdan başka bir sırada olması halinde , bu komutun işe yaramayacağını unutmayın.

Kaynak: tüm satırları Ters ve g Güç vim Wikia de.

Harici komutları kullanarak birkaç örnek:

  • tac( GNU coreutils'in bir kısmı - catters):

    :%!tac                                                                                                                                                                                                                                                              
    
  • tail BSD / OSX’te (POSIX uyumlu değil):

    :%!tail -r
    

    -r -R seçeneği, girişin satır sırasına göre ters sırada görüntülenmesine neden olur.

    man tarDaha fazla bilgi için kontrol edin .

Daha fazla fikir için, bkz:


2
:g/^/m0Aynı :g/^/move 0, John'un cevabı hangisi değil ?
muru

@muru Sanırım, ama bu daha kısa (vim wikia'ya göre) ve komut satırlarını kullanmanın birkaç ek örneğiyle farklı bir açıklama ekledim.
kenorb

Evet, diğer komutlardan dolayı fazla oy aldım (Ben de göndermeye geldim tac). Ancak asıl oylamanın, yanıtın tekrarı olmasından kaynaklandığından şüpheleniyorum.
muru

tacOP tarafından belirtildiğinin farkındayım , ancak diğer tüm benzer sorular yine de bunun kopyası olacak, bu yüzden tekrar söylemekten iyidir. John bu cmd'yi @tommcdo yorumundan aldı, başlangıçta DerMike'dan aldım , ama sanırım sadece wikia'dan aldı, bu yüzden vim wikia'ya kredi verdim, bu yüzden açıklama tamamen farklı değil.
kenorb

Doğru açıklama ile çok daha kısa sürüm olduğundan ve doğru kaynakları da kredilendirdiğim için daha fazla değer katar. Kabuk komutlarını kullanmak çok basit ve kullanışlıdır. Eğer insanlar aynı fikirde olmazsa, basitçe aşağı oy kullanabilirler, önemli değil.
kenorb

6

İşlevsel VimL ruhunda:

:call setline(1, reverse(getline(1, line('$'))))
  • getline(1, line('$'))Tampondaki tüm satırların listesini döndürür. arabellekteki son satırı belirten '$'özel bir argümandır line().
  • reverse(...)yerinde giriş listesini tersine çevirir. Bir kullanmak gerekir reverse(copy(...))girdi listesi değiştirilmemelidir eğer.
  • setline(1, ...)belirtilen satırı ikinci argümanla değiştirir. İkinci argüman bir liste olduğunda, listenin uzunluğuyla aynı sayıda satır listenin içeriği ile değiştirilir.

İsterseniz, aralık alan bir komut da tanımlayabilirsiniz (varsayılan %tüm tampon)

:command! -bar -range=% Reverse call setline(<line1>, reverse(getline(<line1>, <line2>)))

1
Bu cevabı beğendim. Aynı zamanda (eğer hlsearchetkinse) :g/diğer cevaplardan gelen komut gibi şeyleri vurgulamıyor ... Performans, belki de daha kötü, değil mi? O yana getline(1, line('$'))bellekte tüm tampon alır. reverse()yerinde göründüğü için çok az hafıza alması gerekiyor ...
Martin Tournoij

3

Vim Belgelerine Göre usr_12.txt - Zekice Püf Noktaları

12.4 Ters sıra sırası

:globalKomut ile kombine edilebilir :movebir ters dosya sonuçlanan ilk çizgi önce tüm satırları taşımak için komut. Komut:

:global/^/m 0

Kısaltılmış:

:g/^/m 0

^Düzenli ifade hattı (hat boş olsa bile) başıyla eşleşir. :moveMevcut eşleme hattı dosyasının ilk satırını olur böylece komut, efsanevi sıfırıncı satırdan sonra eşleşme hattını taşır. Gibi :globalkomut değiştirerek satır numaralandırma tarafından karışık değildir, :globaldosya ve ilk olarak koyar her kalan tüm satırları maç için ilerler.

Bu aynı zamanda çeşitli hatlarda da çalışır. İlk önce ilk satırın üstüne gidin ve ile işaretleyin mt. Ardından imleci aralıktaki son satıra getirin ve şunu yazın:

:'t+1,.g/^/m 't

1

Göreceli sayıları kullanma. Paragraf 13 satırında başlar ve 4 satırdan fazla spam gönderir

 :13,13+4g/^/m12
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.