Як я можу конвертувати пробіли у вкладки у Vim чи Linux?


192

Я переглянув декілька питань щодо переповнення стека щодо того, як перетворити пробіли на вкладки, не знайшовши, що мені потрібно. Здається, виникає більше запитань щодо того, як перетворити вкладки в пробіли, але я намагаюся зробити навпаки.

В VimЯ намагався :retabі :retab!без везіння, але я вважаю , ті , насправді для переходу з вкладок простору в будь-якому випадку.

Я спробував і те, expandі unexpandв командному рядку без жодної удачі.

Ось файл, про який йде мова:

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

Як я можу конвертувати провідні пробіли у вкладки за допомогою Vimабо оболонки?


У коментарі @ Метта, який зараз видалено, з'являється перший приклад ( sed "s/ +/`echo -e '\t'`/g" < input.py > output.py) для перетворення всіх пробілів, а не лише провідних пробілів. У другому прикладі ( sed "s/^ +/`echo -e '\t'`/g" < input.py > output.py) він лише замінює перший пробіл у кожному рядку на вкладку і залишає решту з них.
cwd


Я не знайшов відповіді на всі / багато файлів , тому написав власний: stackoverflow.com/a/44581474/1115187 . З find, awkі блекджек (занадто довго, щоб залишати це в коментарях, хоча)
maxkoryukov

Відповіді:


316

Використовуючи Vim для розширення всіх провідних просторів (ширше, ніж 'tabstop'), ви мали рацію, retabале спочатку переконайтеся 'expandtab', що скидається ( :verbose set ts? et?це ваш друг). retabзаймає діапазон , тому я зазвичай вказую %значення "весь файл".

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

Перш ніж робити щось подібне (особливо з файлами Python!), Я зазвичай встановлюю 'list'так, щоб я міг бачити пробіл і змінюватися.

У мене є таке відображення в Моєму.vimrc для цього:

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

2
ось як я отримав його на роботу, не впевнений , що потрібно , а що ні, і до речі я не знаю , що таке «%» перед reatab робить: :set noet, :set tabstop=2, :retab!, :%retab!, :set tabstop=1, :retab!,:%retab!
ВУХО

2
Я оновив свою відповідь, щоб включити пояснення, чому я використовую %. Відображення F2 точно так, як воно набрано .
Johnsyweb

7
Для цього конкретного файлу я просто зробив би::set noet ts=2 |%retab!
Johnsyweb

1
@Johnsyweb, щоб бути справедливим, я помилявся: :%retab!усе ще працює. Мене плутали і ==т. Д., Що поважає умови зберігання.
Unk

1
Для перетворення файлу coffeescript з пробілів у вкладки я дотримувався відповіді @ Johnsyweb (включаючи додавання до файлу .vimrc), але замість цього:set tabstop=4
Mikeumus

38

1 - Якщо у вас є пробіли та ви хочете вкладки.

Спочатку потрібно визначитися, скільки пробілів матиме одна вкладка. При цьому, припустимо, у вас є рядки з провідними 4 пробілами, або 8 ... ніж ви усвідомлюєте, що ви, мабуть, хочете, щоб на вкладці було 4 пробіли. Тепер з цією інформацією ви робите:

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

Тут є проблема! Ця послідовність команд буде шукати весь ваш текст, а не лише пробіли на початку рядка. Це означає, що рядок типу: "Hey,␣this␣␣␣␣is␣4␣spaces"стане "Hey,␣this⇥is␣4␣spaces", але його немає! його вкладка !.

Щоб вирішити цю маленьку проблему search, замість цього я рекомендую retab.

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

Цей пошук буде шукати у всьому файлі будь-які рядки, починаючи з будь-якої кількості вкладок, а потім 4 пробіли, і замінить його будь-якою кількістю вкладених файлів плюс один.

Це, на жаль, запуститься не відразу!

Спочатку у файлі будуть рядки, що починаються з пробілів. Після цього пошук конвертуватиме лише перші 4 пробіли на вкладку, і нехай наступне ...

Вам потрібно повторити команду. Скільки разів? Поки ти не отримаєш pattern not found. Я поки не можу придумати спосіб автоматизації процесу. Але якщо ви робите:

`10@:`

Ви, мабуть, зробили. Ця команда повторює останній пошук / заміну 10 разів. Ймовірно, у вашій програмі буде стільки відступів. Якщо є, просто повторіть ще раз @@.

Тепер лише для завершення відповіді. Я знаю, що ви просили навпаки, але ніколи не знаєте, коли потрібно скасувати речі.

2 - У вас є вкладки та потрібні пробіли.

По-перше, визначте, у скільки просторів потрібно перетворити ваші вкладки. Скажімо, ви хочете, щоб у кожній вкладці було 2 пробіли. Потім ви робите:

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

Це матиме ту саму проблему з рядками. Але, оскільки його кращий стиль програмування не використовувати жорсткі вкладки всередині рядків, ви насправді робите це добре. Якщо вам дійсно потрібна вкладка всередині рядка, використовуйте \t.


Здається, надзвичайно рідкісний стан гонки. У будь-якому випадку, створіть функцію, що приймає вибір візуального діапазону і ітерацію функції пошуку, поки не знайдено відповідності, я думаю, це була б більш розумна і корисна відповідь.
albfan

Так, або це. Якщо ви хочете більш чіткого рішення, ви можете скористатися функцією. У будь-якому випадку, завжди добре знати, як це робити ex command, тому що це було б всередині функції. І ні, це не рідко. Вам просто потрібно мати рядки з пробілами, щоб мати безлад. Зовсім не рідкість. Я там буваю. Дякуємо за коментар.
Д-р Беко

Поясніть, чому / g недостатньо для перетворення всіх груп із 4 у кожному рядку послідовних пробілів у вкладки, замість того, щоб запускати пошук кілька разів.
Bjartur Thorlacius

Привіт @BjarturThorlacius, проблема полягає в тому, що якщо ви видалите ^символ, щоб почати пошук з початку рядка, ви ризикуєте змінити пробіли всередині рядків. З ^гарантією ви змінюєте лише пробіли та вкладки з початку рядка, таким чином, відступ. Крім того, якщо ви впевнені, що це все добре відразу, видаліть ^і запустіть лише один раз::%s/\(^I*\)␣␣␣␣/\1^I/g
Д-р Беко

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

Переклад: шукайте кожен екземпляр із 4-х послідовних пробілів (після символу =), але лише якщо весь рядок до цієї точки є пробілом (для цього використовується твердження нульової ширини ззаду, \@<=). Замініть кожен знайдений екземпляр символом вкладки.


1
Єдине рішення, яке працювало на розширенні 1 простору на 1 вкладку , але будьте обережні унікоді у відповіді, я щойно використав :%s/\(^\s*\)\@<= /\t/g- поставити відповідну кількість пробілів (перетворити 4 пробіли на 1 вкладку, помістити в 4 пробіли) відразу після<=
Orwellophile

5

Змінює всі пробіли на вкладці:% s / \ s / \ t / g


Це саме те, що мені було потрібно. Дякую. Єдиною зміною, яку я повинен був зробити, було замінити кожні 4 пробіли вкладкою, а не робити кожен пробіл.
Анонімна особа

3

Linux: з unexpandexpand)

Ось дуже вдале рішення: https://stackoverflow.com/a/11094620/1115187 , здебільшого тому, що він використовує * nix-утиліти:

  1. unspand - пробіли -> вкладки
  2. розгорнути - вкладки -> пробіли

Linux: користувацький сценарій

Моя оригінальна відповідь

Фрагмент Bash для заміни відступу 4- просторів ( {4}у сценарії є два ) з вкладками у всіх .pyфайлах ./appпапки (рекурсивно):

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

Він не змінює 4-пробіли посередині чи в кінці.

Пройшов тестування під Ubuntu 16.0x та Linux Mint 18


0

У моєму випадку у мене було кілька пробілів (поля були розділені одним або кількома пробілами), які я хотів замінити вкладкою. Зробили це:

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

0

Якщо у вас встановлені Coreutils GNU, розгляньте %!unexpand --first-onlyабо для 4-пробільних вкладок, врахуйте %!unexpand -t 4 --first-only( --first-onlyце існує на випадок, якщо ви випадково зверталися unexpandдо нього --all).

Зауважте, що це замінить лише пробіли, що передують встановленим зупинкам вкладки, а не пробіли, які слідують за ними; ви не побачите візуальної різниці в vim, якщо ви не відображатимете вкладки більш буквально; наприклад, мій ~/.vimrcмістить set list listchars=tab:▸┈(я підозрюю, що саме тому ви думали, що unexpandце не працює).


0

Щоб використовувати Vim для повторного введення набору файлів (наприклад, усіх файлів * .ts в ієрархії каталогів), скажімо, 2 пробіли до 4 пробілів, ви можете спробувати це з командного рядка:

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

Для цього findпотрібно передати всі відповідні файли xargs(параметр -print0 при пошуку працює з опцією -0 до xargs, щоб обробляти файли з пробілами в імені).

xargs запускає vim у колишньому режимі ( -e) для кожного файлу, виконуючи дану команду ex, яка насправді є декількома командами, щоб змінити існуючі провідні пробіли на вкладки, скидання зупинки вкладки та повернення вкладок до пробілів і нарешті збереження та вихід.

Запуск у колишньому режимі запобігає цьому: Vim: Warning: Input is not from a terminalдля кожного файлу.


-1

Простий сценарій Python:

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

Одне величезне питання: цей фрагмент замінює всі 4 пробіли, не тільки відступ (на початку рядка)
maxkoryukov

і друге: file-filter не реалізований
maxkoryukov
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.