ค้นหาเป็นกลุ่มและแทนที่ข้อความที่เลือก


109

สมมติว่าเรามีข้อความและฉันเข้าสู่โหมดภาพและเลือกข้อความ ฉันจะค้นหาข้อความที่ไฮไลต์อย่างรวดเร็วและแทนที่ด้วยสิ่งอื่นได้อย่างไร

คำตอบ:


136

ลองดำเนินการต่อไปนี้หรือใส่ลงในไฟล์ .vimrc

vnoremap <C-r> "hy:%s/<C-r>h//gc<left><left><left>

เมื่อกดctrl+ rในโหมดภาพคุณจะได้รับแจ้งให้ป้อนข้อความที่จะแทนที่ด้วย กดenterแล้วยืนยันการเปลี่ยนแปลงแต่ละคุณเห็นด้วยกับหรือลดลงด้วยyn

คำสั่งนี้จะแทนที่รีจิสเตอร์ของคุณhเพื่อให้คุณสามารถเลือกอันอื่น (โดยเปลี่ยนhในคำสั่งด้านบนเป็นตัวอักษรตัวพิมพ์เล็กอื่น) ที่คุณไม่ได้ใช้


13
หากคุณไม่ใส่cในการgcแทนที่จะทำพร้อมกันในบัฟเฟอร์ทั้งหมด หากคุณทำผิดพลาดและต้องการเปลี่ยนกลับเพียงพิมพ์uในโหมดคำสั่ง ฉันชอบวิธีนี้ดีกว่าการยืนยันการเปลี่ยนแต่ละครั้ง (ซึ่งเกิดขึ้นกับcตัวปรับแต่ง)
Niloct

3
vmap * y:let @/ = @"<CR>เลือกจะถูกเน้น
kev

8
เป้าหมายของ<left><left><left>อะไร?
aymericbeaumet

7
@aymericbeaumet เพื่อให้เคอร์เซอร์อยู่ระหว่างเครื่องหมายทับไปข้างหน้าทั้งสองเพื่อให้สามารถพิมพ์คำแทนที่ได้อย่างง่ายดาย
mcabrams

5
โปรดทราบว่าถ้าคุณใช้ @ ข้อเสนอแนะเกี่ยวกับ Niloct ลบcจากgcคุณยังจะต้องเอาหนึ่งใน<left>'s จากจุดสิ้นสุดของเส้น
Nathan Friend

36

การค้นหาการทำแผนที่ที่ง่ายและรวดเร็วนี้สำหรับข้อความที่ไฮไลต์ด้วยภาพ (โดยไม่ต้องเขียน h register มากเกินไป) และไม่ใช้เทอร์มินัลขึ้นอยู่กับ + register:

" search for visually hightlighted text
vnoremap <c-f> y<ESC>/<c-r>"<CR>   

หากคุณไม่ชอบ ctrl-f ให้เปลี่ยนเป็นค่ากำหนดของคุณ

เมื่อไฮไลต์ข้อความแล้วคุณสามารถทำการsubstitution ได้ตลอดเวลาเพียงแค่พิมพ์:

%s//<your-replacement-string>

... เนื่องจากการค้นหาว่างในsคำสั่งใช้สตริงที่ค้นหาล่าสุด


เมื่อฉันใช้สิ่งนี้ในการกำหนดค่าเป็นกลุ่มให้control+fเลือกอักขระถัดไปตลอดจนสิ่งที่ฉันเลือกด้วยสายตา ความคิดใด ๆ ?
Robert Mark Bram

%s//<your-replacement-string>/tmp/fileดูเหมือนจะไม่ทำงานสำหรับไฮไลต์สิ่งที่ต้องการ มันจะกลายเป็น<your-replacement-string>/tmp/file
naisanza

29

ใช้งานได้เช่นกัน (อย่างน้อยสำหรับการเลือกในบรรทัดเดียว / การเลือกที่ไม่มีอักขระพิเศษใด ๆ )

  • เลือกข้อความในโหมดภาพ
  • ดึงข้อความด้วย y
  • :s/<C-r>0/

0 คือการลงทะเบียน yank

อย่างที่คนอื่น ๆ พูดถึงมีวิธีที่เร็วกว่านี้ แต่ถ้าคุณเพิ่งเริ่มเรียนรู้ Vim (เหมือนฉัน) นี่เป็นวิธี 'ทั่วไป' วิธีหนึ่ง

// แก้ไข: ฉันเพิ่งรู้ว่าวิธีการ 'ลงทะเบียน' จะล้มเหลวหากมีอักขระเช่นแท็บหรือบรรทัดใหม่หรือ/อักขระในการเลือก (ฉันต้องประมวลผลอักขระเหล่านั้นด้วยตนเองเพื่อให้:sคำสั่งทำงาน):

ใส่คำอธิบายภาพที่นี่


2
มันง่ายมาก โอ้พระเจ้าทำไมมันไม่ครอบคลุมใน wiki มาเลย ... ขอบคุณสำหรับคำตอบ!
Benyamin Limanto

2
นี่คือคำตอบที่ดีสำหรับพวกเราที่ยังอยู่ในช่วงเริ่มต้นของเส้นโค้งการเรียนรู้แบบกลุ่ม ฉันรู้ว่าการปรับแต่งเป็นจุดแข็ง แต่ฉันไม่ต้องการคัดลอก - วางสคริปต์ที่ซับซ้อนลงใน vimrc ของฉันและไขปริศนาว่ามันเข้ากันได้อย่างไรสำหรับปัญหาที่เรียบง่ายเช่นนี้ คำตอบนี้สอนฉันว่า ctrl-R ทิ้งรีจิสเตอร์ซึ่งจะสะดวกในการจดจำในบริบทอื่น ๆ
nivek

26

คำตอบที่ยอมรับจะใช้งานได้ดีเว้นแต่คุณจะมีอักขระพิเศษในการเลือกภาพ ฉันแฮ็คสองสคริปต์เข้าด้วยกัน ( โพสต์ของJeremy Cantrellที่นี่และPeter Odding ) เพื่อสร้างคำสั่งที่จะช่วยให้คุณสามารถมองเห็นภาพเลือกสตริงที่คุณต้องการค้นหาแม้ว่าจะมีอักขระ regex พิเศษอยู่ก็ตาม

" Escape special characters in a string for exact matching.
" This is useful to copying strings from the file to the search tool
" Based on this - http://peterodding.com/code/vim/profile/autoload/xolox/escape.vim
function! EscapeString (string)
  let string=a:string
  " Escape regex characters
  let string = escape(string, '^$.*\/~[]')
  " Escape the line endings
  let string = substitute(string, '\n', '\\n', 'g')
  return string
endfunction

" Get the current visual block for search and replaces
" This function passed the visual block through a string escape function
" Based on this - /programming/676600/vim-replace-selected-text/677918#677918
function! GetVisual() range
  " Save the current register and clipboard
  let reg_save = getreg('"')
  let regtype_save = getregtype('"')
  let cb_save = &clipboard
  set clipboard&

  " Put the current visual selection in the " register
  normal! ""gvy
  let selection = getreg('"')

  " Put the saved registers and clipboards back
  call setreg('"', reg_save, regtype_save)
  let &clipboard = cb_save

  "Escape any special characters in the selection
  let escaped_selection = EscapeString(selection)

  return escaped_selection
endfunction

" Start the find and replace command across the entire file
vmap <leader>z <Esc>:%s/<c-r>=GetVisual()<cr>/

ฉันได้รวมสิ่งนี้ไว้ในvimrcของฉันหากมีประโยชน์มากกว่าสำหรับทุกคน


2
ขอบคุณสำหรับวิธีแก้ปัญหาการรวมข้อเสนอหลายข้อฉันลงเอยด้วยสิ่งต่อไปนี้: vmap <C-r> <Esc>:%s/<c-r>=GetVisual()<cr>//g<left><left>(ซึ่งเพิ่งแทนที่ทั้งหมดในไฟล์)
Peter Butkovic

13

จาก Vim 7.4 คุณสามารถใช้การgnเคลื่อนไหวซึ่งเลือกพื้นที่ของข้อความที่ตรงกับรูปแบบการค้นหาปัจจุบัน

หลังจากใช้cgnเพื่อเปลี่ยนข้อความในการจับคู่ที่เลือกในปัจจุบัน (หรือdgnเพื่อลบ) ในโหมดปกติคุณสามารถใช้.เพื่อทำคำสั่งซ้ำและดำเนินการในนัดถัดไป

มีตอนของ Vimcast ที่แสดงคุณสมบัตินี้


3
นี่ตอบโจทย์มาก!
mauriciojost

นี่ก็ยอดเยี่ยมเช่นกัน นอกเหนือจากคำตอบของโคลมิก เยี่ยมมาก!
Benyamin Limanto

ว้าวมันเหมือนความลับอย่างหนึ่งที่คุณพบเมื่อท่องลึก ๆ เพื่อหาทางออกที่ดีขอบคุณ
vdegenne

8

Mykola Golubyev ขอบคุณสำหรับเคล็ดลับ! ต่อไปนี้ใช้รีจิสเตอร์ "+" ซึ่ง (ขึ้นอยู่กับเทอร์มินัลของคุณ) มีข้อความที่ไฮไลต์อยู่แล้วประหยัดจากการใช้รีจิสเตอร์ "h"

vnoremap <C-r> <Esc>:%s/<C-r>+//gc<left><left><left>

VIM 7.0 ของฉันบน CentOS 5.x ดูเหมือนจะไม่มีการลงทะเบียน + นี่เป็นคุณสมบัติมาตรฐานหรือไม่?
dotancohen

3
ฉันทราบว่าฉันเข้าถึงเครื่อง CentOS ผ่าน Putty และเมื่อ googling ฉันเห็นว่า + คือการลงทะเบียนคลิปบอร์ด สีโป๊วดูเหมือนจะไม่รองรับ! ดังนั้นคำตอบนี้จึงขึ้นอยู่กับเทอร์มินัล
dotancohen

สวัสดีฉันลองใช้คำสั่งของคุณแล้ว แต่ขอให้ฉันแทนที่การเกิดขึ้นของข้อความที่ระบุตลอดทั้งไฟล์ไม่ใช่แค่ข้อความที่เลือก
solalito

7

จากhttp://vim.wikia.com/wiki/Search_and_replace_in_a_visual_selection :

เมื่อข้อความถูกเลือกด้วยสายตาให้กด: เพื่อป้อนคำสั่ง บรรทัดคำสั่งจะเข้าสู่ช่วงโดยอัตโนมัติ:

:'<,'>

คุณสามารถป้อนคำสั่งเช่น s / red / green / g เพื่อแทนที่แต่ละสีแดงด้วยสีเขียวในทุกบรรทัดของการเลือกภาพสุดท้าย คำสั่งจะปรากฏเป็น:

:'<,'>s/red/green/g

หากต้องการทำซ้ำคำสั่ง Ex บนบล็อกที่เลือกไว้ก่อนหน้านี้ให้ใช้: history นั่นคือกด: จากนั้นแก้ไขคำสั่งก่อนหน้า


4
ใช่สิ่งนี้แทนที่สีแดงด้วยสีเขียวในพื้นที่ที่เลือก - มีประโยชน์มาก แต่ไม่ใช่สิ่งที่ฝ่ายปฏิบัติการขอ
ErichBSchulz

@ErichBSchulz มันทำได้จริงในทุกบรรทัดที่เลือก ดังนั้นแม้ว่าจะเลือกเพียงบางส่วนของบรรทัด แต่ก็จะทำกับทั้งบรรทัด
Cully

1
บางทีอาจไม่ตอบคำถาม OP แต่สิ่งนี้ตอบโจทย์การค้นหาของฉันอย่างแท้จริง "ค้นหาเป็นกลุ่มและแทนที่ด้วยการเลือกภาพ" ซึ่งฉันต้องการ จำกัด การค้นหาและแทนที่เฉพาะการเลือกภาพเท่านั้นซึ่งจะทำให้เกิดคำถามนี้ขึ้น
icc97

5

ฉันมีสิ่งนี้ใน vimrc ของฉัน:

function! GetVisual() range
    let reg_save = getreg('"')
    let regtype_save = getregtype('"')
    let cb_save = &clipboard
    set clipboard&
    normal! ""gvy
    let selection = getreg('"')
    call setreg('"', reg_save, regtype_save)
    let &clipboard = cb_save
    return selection
endfunction

vmap <leader>z :%s/<c-r>=GetVisual()<cr>/

สิ่งนี้จะดึงการเลือกภาพและเริ่มคำสั่งการทดแทนด้วย

แก้ไข: ฉันควรชี้ให้เห็นว่าสิ่งนี้ใช้ไม่ได้กับการเลือกภาพหลายเส้น แม้ว่า GetVisual () จะไม่มีปัญหาในการส่งคืน แต่ฉันไม่แน่ใจว่าจะใส่ลงในบรรทัดคำสั่งได้อย่างไร หากใครมีเคล็ดลับว่าฉันจะทำอย่างไรโปรดแสดงความคิดเห็น


2

ฉันไม่คิดว่าคุณจะทำได้นอกกรอบ แต่ผู้คนจำนวนมากชอบฟีเจอร์นี้ดังนั้นจึงมีมาโครมากมายและเช่นนั้น (ฉันได้เพิ่มเอง) นี่คือสิ่งที่คุณสามารถเพิ่มได้เช่น เพียงแค่กด*เพื่อค้นหารายการที่ตรงกันถัดไปบนข้อความที่เลือกด้วยภาพ


2

คำตอบอื่น ๆ ดี แต่ไม่หนีอักขระพิเศษ คำตอบของ @ Brian kennedy แสดงให้เห็นถึงวิธีการที่จะหลบหนี แต่ต้องใช้รหัสมาก ในกรณีของ URL ตัวอย่างเช่นการใช้ Escape เป็นสิ่งที่จำเป็นไม่เช่นนั้นการค้นหาจะหยุดบน“:”

ตามที่เขียนไว้ในvim.fandom.com/wiki/Search_for_visually_selected_textคุณสามารถใช้ oneliner เพื่อค้นหาและหลีกเลี่ยงอักขระบางตัวได้ คุณสามารถหลบหนีตัวละครที่คุณต้องการฉันเลือกที่จะหลบหนี/\: :

vnoremap // y/\V<C-R>=escape(@",'/\:')<CR><CR>

ด้วยแผนที่นี้ฉันต้องกด//ในโหมดภาพเพื่อค้นหาข้อความที่เลือกในปัจจุบันในบัฟเฟอร์ทั้งหมด


1

เวอร์ชันสั้นที่ฉันชอบคือ

vnoremap s / y: s / "/

จากนั้นคุณสามารถไฮไลต์ส่วนที่เลือกและเพียงแค่กด s / เพื่อเริ่มคำสั่งการแทนที่


ไม่ได้ผลสำหรับฉันถือว่า"เป็นตัวอักษร <c-r>"ทำงานแม้ว่า
Josh Bodah

1

ฉันไม่มีตัวแทนที่จะแสดงความคิดเห็นดังนั้นฉันจึงเพิ่มคำตอบอื่น ...

vnoremap <C-r> "0y<Esc>:%s/<C-r>0//g<left><left>

@dmd และ @dotancohen: สิ่งนี้ใช้ได้กับฉันโดยไม่ต้องใช้จนหมด"h(ใช้ 0 อย่างชัดเจนซึ่งเป็นตำแหน่งสุดท้ายที่ดึงอยู่แล้ว) และใช้งานได้กับผงสำหรับอุดรู ssh -> mint (lmde); ไม่รู้เรื่องร้อยละ ยังใช้ความคิดเห็นของ @Niloct และ @Nathan Friend เพื่อลบการยืนยัน


1

ตัวอย่าง 1. การเลือกใบเสนอราคาด้วยดาวให้เคอร์เซอร์ไว้ที่จุดเริ่มต้นของการเลือก

:%s,\%#\%V\_.*\%V/,**&**,c 

ตัวอย่างที่ 2. ไพพ์ข้อความที่เลือกด้วย base64:

:%s!\%#\%V\_.*\%V!\=system("base64 -w 0",@")!c

คำอธิบาย LHS:

\%# matches cursor 
\%V matches inside the selection only
\_. matches any character.
\_.* matches beginning to end of selection.

คำอธิบาย RHS:

\=expr()  Replace match with result of expr() for each substitution.

0

ฉันหวังว่าจะมีการสร้างขึ้นใน Vim เพื่อแทนที่คำโดยไม่ต้องพิมพ์คำใหม่ตั้งแต่แรก แม้ว่าจะใช้ได้กับข้อความที่มีอักขระขอบเขตคำเท่านั้น

เมื่อคุณวางเมาส์เหนือคำนั้นแล้วให้กด*หรือ#เพื่อไฮไลต์คำนั้นแล้วข้ามไปยังตำแหน่งถัดไป / ก่อนหน้าของคำนั้น (หากคุณไม่ต้องการเปลี่ยนตำแหน่งในไฟล์ให้กดปุ่มตรงข้ามเพื่อกลับไปที่ตำแหน่ง คุณอยู่ที่)

จากนั้นพิมพ์:

%s//<your-replacement-string>

ดังที่กล่าวไว้ในคำตอบของบุคคลอื่นหาก%sได้รับรายการว่างระหว่างเครื่องหมายทับก็จะใช้คำที่ค้นหาก่อนหน้านี้ โดยการกด*หรือ#คุณกำลังค้นหาคำที่อยู่ใต้เคอร์เซอร์ซึ่งทำให้เป็นคำที่ค้นหาล่าสุด

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

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