Boşlukları Vim veya Linux'ta sekmelere nasıl dönüştürebilirim?


192

İhtiyacım olanı bulmadan boşlukları sekmelere dönüştürmek için Stack Overflow ile ilgili birkaç soruya baktım. Sekmeleri boşluklara dönüştürme hakkında daha fazla soru var gibi görünüyor, ama tam tersini yapmaya çalışıyorum.

Gelen Vimdenedim :retabve :retab!şans olmadan, ama ben inanıyorum bu durumda boşluk sekmeleri giden için aslında.

Her ikisini de denedim expandve unexpandkomut isteminde hiç şans olmadan.

Söz konusu dosya:

http://gdata-python-client.googlecode.com/hg-history/a9ed9edefd61a0ba0e18c43e448472051821003a/samples/docs/docs_v3_example.py

Önde gelen boşlukları Vimveya kabuğu kullanarak sekmelere nasıl dönüştürebilirim ?


Şimdi silinen @ Matt'in yorumunda, ilk örnek ( sed "s/ +/`echo -e '\t'`/g" < input.py > output.py) yalnızca önde gelen boşlukları değil tüm boşlukları dönüştürür. İkinci örnekte ( sed "s/^ +/`echo -e '\t'`/g" < input.py > output.py) yalnızca her satırdaki ilk boşluğu bir sekme ile değiştirir ve geri kalanını bırakır.
cwd


Tüm / birçok dosya için cevap bulamadım , bu yüzden kendi dosyamı yazdım: stackoverflow.com/a/44581474/1115187 . İle find, awkve blackjack (çok uzun yorumlardaki olsa bırakmak)
maxkoryukov

Yanıtlar:


316

Tüm önde gelen alanları genişletmek için Vim'i (daha geniş 'tabstop') kullanmakta haklıydınız, retabancak önce 'expandtab'sıfırlandığından emin :verbose set ts? et?olun (arkadaşınızdır). retabbir aralık alır , bu yüzden genellikle %"tüm dosya" anlamına gelir.

:set tabstop=2      " To match the sample file
:set noexpandtab    " Use tabs, not spaces
:%retab!            " Retabulate the whole file

(Özellikle Python dosyaları!) İle böyle bir şey yapmadan önce, ben genellikle set 'list'ben böylece o, bkz boşluk ve değişim.

Bunun için benim.vimrc aşağıdaki haritalama var :

nnoremap    <F2> :<C-U>setlocal lcs=tab:>-,trail:-,eol:$ list! list? <CR>

2
i işe aldım nasıl burada, emin gerekli nedir ve ne değildir ve btw reatab önce "%" ne yaptığını bilmiyorum: :set noet, :set tabstop=2, :retab!, :%retab!, :set tabstop=1, :retab!,:%retab!
cwd

2
Cevabımı neden kullandığımla ilgili bir açıklama içerecek şekilde güncelledim %. F2 eşlemesi aynen yazıldığı gibidir .
Johnsyweb

7
Bu özel dosya için şunu yaparım::set noet ts=2 |%retab!
Johnsyweb

1
@Johnsyweb adil olmak, yanılmışım: :%retab!hala çalışıyor. Birlikte karıştı ==hangi vb yapar preserveindent ayarını saygı.
Unk

1
Bir coffeescript dosyasını boşluklardan sekmelere dönüştürmek için @ Johnsyweb'in cevabını (.vimrc dosyasına ek olarak da dahil) takip ettim, bunun yerine bir:set tabstop=4
Mikeumus

38

1 - Boşluklarınız varsa ve sekmeler istiyorsanız.

İlk olarak, kaç boşluğun tek bir sekmeye sahip olacağına karar vermeniz gerekir. Bununla birlikte, 4 boşluklu veya 8 boşluklu satırlarınız olduğunu varsayalım. Şimdi bu bilgi ile şunları yapabilirsiniz:

:set ts=4
:set noet
:%retab!

Burada bir sorun var! Bu komut dizisi, yalnızca satırın başındaki boşlukları değil tüm metninizi arayacaktır. Bu şöyle bir dize anlamına gelir: "Hey,␣this␣␣␣␣is␣4␣spaces"olacak "Hey,␣this⇥is␣4␣spaces", ama değil! onun bir sekme !.

Bu küçük sorunu çözmek için searchbunun yerine bir tavsiye ederim retab.

:%s/^\(^I*\)␣␣␣␣/\1^I/g

Bu arama, hangi sayıda sekme ile başlayıp ardından 4 boşlukla başlayan tüm satırları tüm dosyaya bakacak ve yerine bulduğu sayıda sekme artı bir tane alacaktır.

Bu, ne yazık ki, bir kerede çalışmaz!

İlk başta, dosya boşluklarla başlayan satırlara sahip olacaktır. Arama daha sonra yalnızca ilk 4 boşluğu bir sekmeye dönüştürür ve aşağıdakileri sağlar ...

Komutu tekrarlamanız gerekiyor. Kaç sefer? Bir elde edene kadar pattern not found. Süreci otomatikleştirmenin bir yolunu henüz düşünemiyorum. Ama eğer yaparsanız:

`10@:`

Muhtemelen bitirdiniz. Bu komut son aramayı / değiştirmeyi 10 kez tekrarlar. Programınızın çok fazla girintisi olması muhtemel değildir. Varsa, tekrarlayın @@.

Şimdi, sadece cevabı tamamlamak için. Bunun tam tersini istediğini biliyorum, ama işleri ne zaman geri alman gerektiğini asla bilemezsin.

2 - Sekmeleriniz var ve boşluk istiyorsunuz.

İlk olarak, sekmelerinizin kaç boşluğa dönüştürülmesini istediğinize karar verin. Her sekmenin 2 boşluk olmasını istediğinizi varsayalım. Daha sonra şunları yaparsınız:

:set ts=2
:set et
:%retab!

Bu dizelerle aynı sorunu olurdu. Ancak, dizelerin içindeki sabit sekmeleri kullanmamak için daha iyi programlama stili olduğundan, aslında burada iyi bir şey yapıyorsunuz. Gerçekten bir dize içinde bir sekmeye ihtiyacınız varsa kullanın \t.


Son derece nadir bir yarış durumu gibi görünüyor. Her neyse, görsel aralık seçimini kabul eden bir işlev oluşturun ve hiçbir eşleşme bulunana kadar arama işlevini tekrarlayın, sanırım bu daha akıllı ve kullanışlı bir cevap olacaktır.
albfan

Evet, öyle. Daha kesin bir çözüm istiyorsanız bir fonksiyon kullanabilirsiniz. Her neyse, nasıl yapılacağını bilmek her zaman iyidir ex command, çünkü fonksiyonun içinde olan bu olurdu. Ve hayır, bu nadir değil. Sadece bir karmaşa için boşluklu dizeleri olması gerekir. Hiç de nadir değil. Ben oradayım. Yorum yaptığınız için teşekkürler.
Dr Beco

Lütfen / g'nin, aramayı birden çok kez çalıştırmak yerine ardışık satırlardaki her 4 satırdaki tüm grupları sekmelere dönüştürmek için neden yeterli olmadığını açıklayın.
Bjartur Thorlacius

Merhaba @BjarturThorlacius, sorun, ^sembolü kaldırırsanız , aramayı satırın başından başlatmak için, dize içindeki boşlukları değiştirme riskiniz olmasıdır. Garantiyle birlikte, ^satırın başlangıcından bu yana sadece boşlukları ve sekmeleri değiştirdiğinizden, girinti. Bunun yanı sıra, hepsini bir kerede yapmanın uygun olduğundan eminseniz, şunu çıkarın ^ve yalnızca bir kez çalıştırın::%s/\(^I*\)␣␣␣␣/\1^I/g
Dr Beco

14
:%s/\(^\s*\)\@<=    /\t/g

Çeviri: Art arda 4 boşluktan oluşan her örneği arayın (= karakterinden sonra), ancak yalnızca o noktaya kadar olan tüm satır boşluksa (bu, sıfır genişliğinde arkayı destekleyen iddiayı kullanır \@<=). Bulunan her örneği bir sekme karakteriyle değiştirin.


1
Genişletmek için çalıştı tek çözüm 1 boşluk için 1 sekmesi , ama cevap unicode dikkat, sadece kullanılan :%s/\(^\s*\)\@<= /\t/g- hemen sonra (4 mekanlarda koymak 1 sekmesine 4 boşluk dönüştürmek için) boşluk uygun sayıda koymak<=
Orwellophile

5

Tüm boşlukları sekmeye değiştirir:% s / \ s / \ t / g


Tam da ihtiyacım olan şey bu. Teşekkürler. Yapmam gereken tek değişiklik, her 4 boşluğu bir boşlukla değiştirmek yerine her boşluğu değiştirmekti.
İsimsiz Kişi

3

Linux: ile unexpand(ve expand)

İşte çok iyi bir çözüm: https://stackoverflow.com/a/11094620/1115187 , çoğunlukla * nix-utilities kullandığından:

  1. unexpand - boşluklar -> sekmeler
  2. genişlet - sekmeler -> boşluklar

Linux: özel komut dosyası

Orijinal cevabım

4 boşluklu girintiyi ( {4}komut dosyasında iki tane vardır ) klasördeki tüm .pydosyalarda ./app(yinelemeli olarak) sekmelerle değiştirmek için Bash snippet'i :

find ./app -iname '*.py' -type f \
    -exec awk -i inplace \
    '{ match($0, /^(( {4})*)(.*?)$/, arr); gsub(/ {4}/, "\t", arr[1]) }; { print arr[1] arr[3] }' {} \; 

Ortada veya sonunda 4 boşluk değiştirmez.

Ubuntu 16.0x ve Linux Mint 18 altında test edildi


0

Benim durumumda, bir sekme ile değiştirmek istediğim birden çok boşluk vardı (alanlar bir veya daha fazla boşlukla ayrıldı). Aşağıdakiler yaptı:

:% s/\s\+/\t/g

0

Kurulu GNU coreutils'ınız varsa, %!unexpand --first-only4 boşluklu sekmeler için veya düşünün %!unexpand -t 4 --first-only( --first-onlyyanlışlıkla yanlışlıkla çağırmanız durumunda unexpandmevcuttur --all).

Bunun yalnızca belirtilen sekme duraklarından önceki boşlukların yerini alacağını unutmayın ; bunları izleyen boşlukların değil ; sekmeleri daha tam anlamıyla görüntülemezseniz, vim'de görsel bir fark görmezsiniz; Örneğin, ~/.vimrciçeriğimi set list listchars=tab:▸┈(Bu yüzden unexpandişe yaramadığını düşündüğünüzden şüpheleniyorum ).


0

Vim'i kullanarak 2 boşluktan 4 boşluğa kadar bir dizi dosyayı (örneğin, bir dizin hiyerarşisindeki tüm * .ts dosyalarını) yeniden oluşturmak üzere kullanmak için bunu komut satırından deneyebilirsiniz:

find . -name '*.ts' -print0 | xargs -0 -n1 vim -e '+set ts=2 noet | retab! | set ts=4 et | retab | wq'

Bunun yaptığı findtüm eşleşen dosyaları aktarmak için kullanmaktır xargs(find'daki -print0 seçeneği, addaki boşluklarla dosyaları işlemek için -0 seçeneğiyle xargs'a çalışır).

xargs -e, varolan komut satırlarını sekmeler olarak değiştirmek, sekme durağını sıfırlamak ve sekmeleri tekrar boşluklara değiştirmek ve son olarak kaydedip çıkmak için, aslında birkaç komut olan verilen ex komutunu yürüten her dosyada ex mod ( ) 'da vim çalıştırır.

Eski modda çalıştırmak bunu önler: Vim: Warning: Input is not from a terminalher dosya için.


-1

Basit Python Komut Dosyası:

import os

SOURCE_ROOT = "ROOT DIRECTORY - WILL CONVERT ALL UNDERNEATH"

for root, dirs, files in os.walk(SOURCE_ROOT):
    for f in files:
        fpath = os.path.join(root,f)
        assert os.path.exists(fpath)
        data = open(fpath, "r").read()
        data = data.replace("    ", "\t")
        outfile = open(fpath, "w")
        outfile.write(data)
        outfile.close()

Büyük bir sorun: Bu pasaj , sadece girinti (satırın başında) değil , tüm 4 boşlukların yerini alıyor
maxkoryukov

ve ikinci: dosya filtresi uygulanmadı
maxkoryukov
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.