Який найпростіший спосіб позбавити пробіли з усіх рядків у файлі?


139

Досить часто під час програмування або відкриття текстових файлів зустрічаються файли з пробілом у кінці рядка. vim має змогу показати це, встановивши trailпараметр у listcharsпараметрі та потім увімкнувши list.

Однак який найпростіший спосіб усунути цей пробіл у всьому світі у всьому файлі (в ідеалі без плагіна)?




Якщо ви встановили vim-faq , ви можете отримати офлайн-відповідь там: :h vim-faqта шукайте /trailing. Важко запам'ятовується тег :h faq-12.1.
Hotschke

Відповіді:


72

За допомогою клавіатури зніміть усі пробіли

Оскільки деякі сторінки, які я редагую, насправді потребують пробільних пробілів (наприклад, розмітка), а інші - ні, я встановив прив'язку клавіш F5так, щоб це було тривіально робити, не будучи автоматичним. Для цього додайте код нижче (від vim.wikia) або якусь його змінну до свого .vimrc:

"Remove all trailing whitespace by pressing F5
nnoremap <F5> :let _s=@/<Bar>:%s/\s\+$//e<Bar>:let @/=_s<Bar><CR>
  • nnoremap <F5>робить нерекурсивне відображення ключа F5в звичайному режимі
  • :let _s=@/зберігає останній пошуковий термін (з макросу @/) у змінній_s
  • <Bar>Функції як символ труби |для окремих команд, однак |закінчували б команду в цьому контексті, тому її <Bar>потрібно використовувати.
  • :%s/\s\+$//eшукає пробільний пробіл і видаляє його скрізь у буфері (див . відповідь CarpetSmoker для детального розбиття цього виразу)
  • let @/=_sвідновлює ваш останній пошуковий термін до макросу @/, щоб він був доступний наступного разу, коли ви натиснете n.
  • <CR> закінчується картографування

... або бути більш виборчими

Якщо у вас є випадки, коли ви не хочете позбавити всю пробільну пробіл, ви можете використовувати шаблон, щоб бути більш вибірковим. Наприклад, наступний код показує, як я знімаю пробіли пробілу, лише якщо він з’являється після крапки з комою (тут він прив’язаний F8).

nnoremap <F8> :let _s=@/<Bar>:%s/;\s\+$/;/e<Bar>:let @/=_s<Bar><CR>

Це корисно, якщо, як і я, у вас є деякі файли з розмітками як гередоки, перемежовані серед операторів програмування, що закінчуються крапкою з комою.


6
Намагайтеся :keeppatternsне допустити переосмислення @/. А також погляньте :keepjumps.
Бор

@Bohr Яку версію vim ви використовуєте? Я спробував :help keeppatternі нічого не отримав.
Крістофер Нижній

@ChristopherBottoms Принаймні версія 7.4.155 .
Бор

@Bohr. Дякую! Приходьте, щоб дізнатися, що я все ще використовував 7.4.0. Я встановив останню версію, і вона доступна.
Крістофер Ботс

2
Такий же ефект можна отримати, увімкнувши цю команду у функцію, оскільки тоді останній пошуковий термін автоматично відновлюється :-) Таким чином, вам не доведеться знущатися з :nohlбудь-яким, якщо ви щось підкреслювали, воно буде продовжувати виділяти це (див. мою оновлену відповідь).
Martin Tournoij

175

"Найпростіший" спосіб - просто використовувати :substitute:

:%s/\s\+$//e
  • :%sдля запуску :substituteдіапазону %, який є всім буфером.
  • \s t відповідати всім символам пробілу.
  • \+ повторити їх 1 або більше разів.
  • $ закріпити в кінці рядка.
  • eПрапор не видасть помилку , якщо немає збігу (тобто файл вже без кінцевих пробілів).

Однак, мабуть, це не найкращий спосіб, оскільки це викликає два побічні ефекти:

  1. він переміщує курсор до останнього збігу;
  2. вона додає команду до історії та історії пошуку;
  3. він скидає останній пошуковий термін.

Ви можете виправити обидва елементи, перетворивши це у функцію:

fun! TrimWhitespace()
    let l:save = winsaveview()
    keeppatterns %s/\s\+$//e
    call winrestview(l:save)
endfun

А потім використовуйте його так:

:call TrimWhitespace()
  1. winsaveview()Чи збережуть поточний «вид», який включає в себе положення курсора, складає, скаче і т.д. winrestview()в кінці буде відновити це зі збережених змінних.
  2. :keeppatternsЗапобігає \s\+$зразок від додавання в історії пошуку.
  3. Останній використаний пошуковий термін автоматично відновлюється після виходу з функції, тому для цього нам більше нічого не потрібно робити.

Оскільки це постійно дратує введення :call, ви можете визначити команду:

command! TrimWhitespace call TrimWhitespace()

Які можна використовувати без :call:

:TrimWitespace

І ви, звичайно, можете прив'язати його до ключа:

:noremap <Leader>w :call TrimWhitespace()<CR>

Деякі люди люблять автоматично робити це перед тим, як записати файл на диск, наприклад:

autocmd BufWritePre * :call TrimWhitespace()

Мені це не подобається, оскільки для деяких форматів потрібен пробільний пробіл (наприклад, Markdown), а в деяких інших випадках ви навіть хочете затримати пробіл у своєму коді (наприклад, форматування електронної пошти та використання --<Space>маркера для позначення початку підпису ).


Режим безсоромного підключення: деякий час тому я написав трохи сценарію Python, щоб очистити пробіл для всього проекту відразу.


1
Якщо ви не хочете створити функцію для переходу до попереднього положення, ви можете просто натиснути ​`​двічі після завершення заміни. Це відкриває можливість створити такий лінійку, як це:%s/\s\+$//e | exe "normal ``"
Neaţu Ovidiu Gabriel

1
@ NeaţuOvidiuGabriel, звичайно, тоді подвійний backtick не буде працювати однаково після виконання oneliner. ;)
Wildcard

Схожі: stackoverflow.com/a/1618401 . Але мені більше подобається код Мартіна.
john cj

11

Щоб видалити всю пробільну пробіл (в кінці кожного рядка), ви можете скористатися командою:

:%s/ \+$//

Для включення вкладок використовуйте \sзамість місця.


З командного рядка:

$ ex +'%s/\s\+$//e' -cwq file.c

Усі файли в поточному каталозі (рекурсивно використовувати **/*.*):

$ ex +'bufdo!%s/\s\+$//e' -cxa *.*

Спосіб Python:

:py import vim
:pydo vim.current.buffer[linenr - 1] = vim.current.buffer[linenr - 1].strip()

або:

:py import vim
:py for i, l in enumerate(vim.current.buffer): vim.current.buffer[i] = l.rstrip()

Використовуйте lstrip()для лівої смуги (задні), rstrip()для правої смуги (провідної) або strip()для зняття з обох кінців.


Ось корисна функція, яка видаляє зайвий пробіл з кінця рядка, який ви можете додати до свого .vimrc:

" Removes superfluous white space from the end of a line
function! RemoveWhiteSpace()
   :%s/\s*$//g
    :'^
    "`.
endfunction

Для цього також існує плагін DeleteTrailingWhitespace .


Виділення білих просторів

Щоб двічі перевірити, чи не залишилися всі пробіли, використовуйте:

  1. Введіть, / $щоб знайти їх. Якщо їх є, vim підкреслить їх для вас.

  2. Використовуйте кольори, щоб виділити їх:

    :highlight ws ctermbg=red guibg=red
    :match ws /\s\+$/
    
  3. Використовуйте видимі символи ( джерело ):

    :set encoding=utf-8
    :set listchars=trail:·
    :set list
    

Дивіться також: Виділіть небажані пробіли

Щоб виділити пробіл пробігу за замовчуванням, ви можете налаштувати .vimrcнаступне:

highlight ws ctermbg=red guibg=red
match ws /\s\+$/
autocmd BufWinEnter * match ws / \+$/

Видалення пробілів за замовчуванням

Якщо ви хочете переконатися, що всі збережені пробіли у файлі автоматично видаляються під час збереження, ви можете додати в свою команду таку команду .vimrc:

autocmd BufWritePre *.c,*.php :%s/ \+$//ge

що не рекомендується, оскільки воно буде позбавляти пробілів пробілів з кожного файлу, який зберігає користувач (навіть там, де потрібен пробіл).


Дивитися також:


5

Подовжуючись на відповідь Крістофера Боттомса : Джонатан Палардді написав добру статтю з цього приводу . У ньому він записує функції, Preserve(command)які зберігають стан редактора (головним чином положення курсору та останній шаблон пошуку) під час виконання довільної команди:

function! Preserve(command)
  " Preparation: save window state
  let l:saved_winview = winsaveview()
  " Run the command:
  execute a:command
  " Clean up: restore previous window position
  call winrestview(l:saved_winview)
endfunction

Перевага полягає в тому, що це багатоцільовість, наприклад, ви можете використовувати його для заміни всіх пробільних пробілів (як це робить Джонатан), зіставивши це на:

nnoremap <F5> :call Preserve("%s/\\s\\+$//e")<CR>

Ви також можете використовувати його для візуального відображення режиму, щоб просто видалити пробіли на візуально вибраних лініях:

xnoremap <F5> :call Preserve("'<,'>s/\\s\\+$//e")<CR>

І ви можете використовувати його для інших дзвінків, наприклад, для форматування всього документа =, зберігаючи своє місце (добре використати інший ключ на цей раз, щоб не конфліктувати):

nnoremap <F6> :call Preserve("normal gg=G")<CR>

І все, і я знайшов цю Preserve(command)функцію гарним інструментом.


2
Останній використаний пошуковий термін повинен бути автоматично збережений, коли ви залишаєте функцію; тому @/не варто вимагати роздумів з цим (у будь-якому випадку).
Martin Tournoij

3
winsaveview()і winrestview()набагато вищі.
Даш-Том-Банг

Абсолютно вірно! Оновлено на основі ваших відгуків.
Олексій

0

Інша версія функції StripTrailingSpaces:

if !exists('*StripTrailingWhitespace')
    function! StripTrailingWhitespace() range
        if !&binary && &filetype != 'diff'
            call Preserve(":" . a:firstline . "," . a:lastline . "s/\\s\\+$//e")
        endif
    endfunction
endif

РЕАЛЬНО В ЦІЙ ФУНКЦІЇ є помилка (ця): можливість не затримується через опцію "діапазон". він видалений, він працює дуже добре, проте я ділюсь кодом, щоб отримати деяку допомогу.

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

Різниця тут полягає в тому, що я можу вибрати діапазон рядків або абзац з, vipі тоді діапазон :'<,'>автоматично з’явиться в командному рядку.

Ідея виникла з поста Без Ермосо .

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