วิธีที่ง่ายที่สุดในการตัดช่องว่างต่อท้ายจากทุกบรรทัดในไฟล์คืออะไร


139

เป็นเรื่องปกติมากเมื่อเขียนโปรแกรมหรือเปิดไฟล์ข้อความเพื่อพบไฟล์ที่มีช่องว่างต่อท้ายที่ท้ายบรรทัด เป็นกลุ่มมีวิธีที่จะแสดงโดยการตั้งค่าที่trailตัวเลือกในlistcharsตัวเลือกและจากนั้นหันlistบน

อย่างไรก็ตามวิธีที่ง่ายที่สุดในการกำจัดช่องว่างต่อท้ายนั้นครอบคลุมทั่วทั้งไฟล์ (โดยไม่ต้องมีปลั๊กอิน)



นี่คือรายการเอกสารในหัวข้อ
Filipp W.

หากคุณติดตั้งเป็นกลุ่มคำถามที่พบบ่อย , คุณจะได้รับคำตอบแบบออฟไลน์ที่นั่นและค้นหา: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>

สิ่งนี้มีประโยชน์ถ้าอย่างฉันคุณมีไฟล์บางไฟล์ที่มีheredocsเหมือน markdown คั่นระหว่างคำสั่งการโปรแกรมที่สิ้นสุดด้วยเครื่องหมายอัฒภาค


6
ลองเพื่อป้องกันไม่ให้เอาชนะ:keeppatterns และยังใช้เวลาดูที่@/ :keepjumps
Bohr

@Bohr คุณเป็นคนรุ่นอะไร ฉันพยายาม:help keeppatternแล้วไม่ได้อะไรเลย
Christopher Bottoms

@ChristopherBottoms อย่างน้อยรุ่น7.4.155
Bohr

@Bohr ขอบคุณ! มาหาฉันยังใช้ 7.4.0 อยู่ ฉันติดตั้งเวอร์ชันล่าสุดและพร้อมใช้งาน
Christopher Bottoms

2
คุณสามารถใช้เอฟเฟกต์เดียวกันได้โดยการห่อคำสั่งนี้ในฟังก์ชั่นตั้งแต่นั้นคำค้นหาสุดท้ายจะถูกกู้คืนโดยอัตโนมัติ :-) ด้วยวิธีนี้คุณไม่ต้องยุ่งกับเรื่องนี้ด้วย:nohlเช่นกันถ้าหากคุณกำลังเน้นบางสิ่ง (ดูคำตอบที่อัปเดตของฉัน)
Martin Tournoij

175

วิธีที่ "ง่ายที่สุด" คือการใช้:substitute:

:%s/\s\+$//e
  • :%sเพื่อรัน:substituteในช่วง%ซึ่งเป็นบัฟเฟอร์ทั้งหมด
  • \s ไม่ตรงกับอักขระช่องว่างทั้งหมด
  • \+ เพื่อทำซ้ำ 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 แต่ฉันชอบรหัสของ Martin มากขึ้น
john cj

11

ในการลบช่องว่างต่อท้ายทั้งหมด (ในตอนท้ายของแต่ละบรรทัด) คุณสามารถใช้คำสั่ง:

:%s/ \+$//

หากต้องการรวมแท็บให้ใช้\sแทนการเว้นวรรค


จากบรรทัดคำสั่ง:

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

ไฟล์ทั้งหมดในไดเรกทอรีปัจจุบัน (ใช้ซ้ำ**/*.*):

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

งูหลามวิธี:

: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. พิมพ์/ $เพื่อค้นหา หากมีบางกลุ่มจะเน้นพวกเขาสำหรับคุณ

  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

Exapnding ในคำตอบที่คริสโตก้นของบิต : โจนาธาน Palardy เขียนบทความที่ดีเกี่ยวกับเรื่องนี้ ในนั้นเขาเขียนฟังก์ชั่น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()เหนือกว่า
dash-tom-bang

ค่อนข้างถูกต้อง! อัปเดตตามความคิดเห็นของคุณ
อเล็กซ์

0

รุ่นอื่นของฟังก์ชั่น StripTrailingSpaces:

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

จริงๆแล้วมีข้อผิดพลาดในฟังก์ชั่นนี้ (อันนี้): การครอบครองไม่ได้ถูกเก็บรักษาไว้เพราะตัวเลือก "ช่วง" มันถูกลบออกมันใช้งานได้ดีมาก แต่ฉันแบ่งปันรหัสเพื่อรับความช่วยเหลือ

อย่างที่คุณเห็นมันยังใช้ฟังก์ชั่นPreserve ที่เห็นด้านบน แต่แตกต่างกันเล็กน้อย

ความแตกต่างที่นี่คือฉันสามารถเลือกช่วงของบรรทัดหรือย่อหน้าด้วยvipจากนั้นช่วง:'<,'>จะปรากฏขึ้นที่พรอมต์คำสั่งโดยอัตโนมัติ

ความคิดที่มาจาก Bez Hermoso โพสต์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.