ค้นหาธรรมดาและแทนที่เช่น Notepad?

Aug 21 2020

ฉันทราบถึงsubstituteคำสั่งและการใช้งานเป็นคำสั่ง ex:%s/<old>/<new>/g

อย่างไรก็ตามเมื่อ<new>มีสตริงที่ซับซ้อนมากให้พูด URL ที่ซับซ้อนที่มีอักขระจำนวนมากเช่น% [ ] : / \ฯลฯ จากนั้นอักขระจะเริ่มเป็นส่วนหนึ่งของคำสั่ง (โดยเฉพาะ/หรือ:) และฉันต้องเริ่มใช้ลำดับการหลีกเลี่ยงเช่น\

มีวิธีการเปลี่ยนออกทั้งหมดที่จำเป็นสำหรับการหลบหนีและทุกการตีความเพื่อที่ฉันสามารถแทนที่<old>ด้วย<new>แม้ว่า<old>และ<new>มีอักขระ ASCII พลรวมทั้ง/ : [ ] % # $ ( )etc?

ตอนนี้ฉันใช้ Notepad เพื่อทำสิ่งนี้ แต่ฉันหวังว่าฉันจะอยู่ใน VIM ได้

คำตอบ

1 eyalkarni Aug 22 2020 at 05:30

สมมติว่าไม่มีรูปแบบ\แล้วสิ่งนี้จะใช้ได้:

:%s/\Vpattern/\='string'

ในทุกกรณีเมื่อสตริงรูปแบบและการแทนที่อยู่ในตัวแปรสิ่งนี้จะใช้ได้:

let pattern='<old>'
let str='<new>'
:exec "s/\\V" . escape(escape( pattern, '\'),'/') . "/\\=str"

แน่นอนคุณสามารถใช้วิธีการต่างๆเช่นinput()หรือคำสั่ง args เพื่อตั้งค่าตัวแปร

PaperclipBob Aug 22 2020 at 08:14

หลังจากอ่านความคิดเห็นเกี่ยวกับคำตอบแรกของฉันฉันรู้ว่าอาจมีวิธีง่ายๆที่แตกต่างจากคำแนะนำแรกของฉันอย่างมาก คำแนะนำใหม่นี้ยังคงต้องใช้ "เป็นครั้งคราว" ในฐานะสแตนด์อินสำหรับการจับคู่อักขระพิเศษ แต่เนื่องจากไม่มีความสามารถที่แท้จริงในการค้นหาสตริงตามตัวอักษรในกลุ่มคุณจึงต้องประนีประนอมในบางลักษณะ มีฟังก์ชันพิเศษที่คุณสามารถสร้างขึ้นซึ่งอาจเหมาะกับคุณ แต่ฉันพบว่าโซลูชันนี้ใช้งานง่ายและใช้งานง่ายมาก

[เนื่องจากโซลูชันนี้แทบจะไม่มีอะไรเหมือนกันกับโซลูชันแรกของฉันฉันจึงโพสต์ไว้เป็นคำตอบที่สองแทนที่จะเป็นการแก้ไขคำตอบแรกของฉัน ถ้าฉันแก้ไขคำตอบทั้งหมดความคิดเห็นที่เป็นประโยชน์หลายอย่างที่สมาชิกคนอื่น ๆ เพิ่มจะไม่สมเหตุสมผลอีกต่อไป]

คำแนะนำใหม่ของฉันมีดังนี้ ..

ก่อนอื่นฉันวางสิ่งนี้ใน. vimrc ของฉัน ...

set incsearch

จาก:h incsearch...

While typing a search command, show where the pattern, as it was typed
so far, matches. The matched string is highlighted. If the pattern
is invalid or not found, nothing is shown. 

[สำหรับตัวอย่างด้านล่างสมมติว่ารูปแบบการค้นหาของคุณเป็นส่วนหนึ่งของคำสั่ง ": global" หรือ ": replace"]

ถ้าคุณต้องการเพื่อให้ตรงกับ URL http:ที่คุณจะเริ่มประเภท ขณะที่คุณพิมพ์โปรดสังเกตว่ารายการที่ตรงกันถัดไปที่เป็นไปได้ในไฟล์ของคุณหรือข้อความที่เลือกจะปรากฏขึ้นและไฮไลต์บนหน้าจอของคุณ เมื่อคุณพิมพ์ตัวอักษรตัวแรก 'h' มันอาจเน้นตัว 'h' ในคำว่า elephant (หาก elephant มี 'h' เป็นครั้งแรกในไฟล์ของคุณหรือในข้อความที่เลือกในปัจจุบัน)

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

คุณพิมพ์ต่อไป อีกตัว 't' ('htt') ตามด้วย 'p' ('http') และเครื่องหมายทวิภาค ('http:') จนถึงตอนนี้ดีมาก URL แรกยังคงถูกเน้นบนหน้าจอของคุณ มันอาจยังไม่ใช่ URL ที่คุณต้องการ แต่อย่างน้อยคุณก็รู้ว่ารูปแบบของคุณจนถึงตอนนี้ ( http:) ใช้งานได้

แต่ทันทีที่คุณพิมพ์ '/' คุณจะสังเกตเห็นว่าการไฮไลต์ไม่ติดตามสิ่งที่คุณกำลังพิมพ์อีกต่อไป เกิดข้อผิดพลาดในการค้นหา "http: /" คุณอาจลืมไปว่า "/" จำเป็นต้องหนี

แต่คุณไม่จำเป็นต้องจำสิ่งที่ต้องหนี !!!

ความคิดเห็นแบบสดเมื่อไม่ตรงกับ URL อีกต่อไปจะบอกคุณได้ทันทีว่าการเพิ่ม "/" เป็น "http:" จะไม่ตรงกับสิ่งใด ๆ

คุณต้องหนีเครื่องหมาย "/" แต่แทนที่จะหนี '/' ฉันชอบที่จะพิมพ์ตัวเดียว '.' เพราะพิมพ์ง่ายกว่า "\ /" แต่คุณสามารถพิมพ์ "." หรือ '\/'

ข้อเสียของแนวทางนี้คือ (1) ไม่ได้ทำไปโดยสิ้นเชิงกับความจำเป็นในการหลบหนีหรือ '.'; และ (2) ตำแหน่งหน้าจอของคุณอาจเคลื่อนผ่านไฟล์ในขณะที่คุณพิมพ์รูปแบบการค้นหาของคุณ

จากประสบการณ์ของฉันไม่มีใครรบกวนฉัน คุณอาจพบเป็นอย่างอื่น

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

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

PaperclipBob Aug 21 2020 at 23:56

.vimrc ของฉันมีบรรทัดเหล่านี้ ...

set incsearch
let @o = ".nzz"
map <F8> @o

คำสั่งเหล่านี้ช่วยให้ฉันทำการแก้ไขได้ทุกประเภทโดยไม่ต้องกังวลว่าจะมีอักขระพิเศษอื่น ๆ ออกมา นอกจากนี้ยังช่วยให้ฉันแก้ไขหลายบรรทัดได้อย่างง่ายดาย

เมื่อคำสั่งเหล่านี้อยู่ใน. vimrc ของคุณแล้วขั้นตอนจะเป็นดังนี้ ...

ขั้นแรกคุณต้องค้นหารูปแบบที่ตรงกับเหตุการณ์ทั้งหมดที่คุณต้องการเปลี่ยนแปลง นี่เป็นสิ่งสำคัญเนื่องจากวิธีแก้ปัญหาของฉันขึ้นอยู่กับการย้ายไปยังเหตุการณ์ถัดไปโดยใช้ตัวดำเนินการ find-next ('n')

ตัวอย่างเช่นหากคุณต้องการแก้ไข URL ทั้งหมดจากโฮสต์ "abcxyz.com" ที่ลงท้ายด้วยพูดว่า. php คุณอาจค้นหา (จากโหมดปกติ) ดังนี้ ..

/http:..abcxyz.com.*.php

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

เมื่อคุณกด Enter และอยู่ในตำแหน่งที่เกิดขึ้นครั้งแรกของ URL คุณจะเปลี่ยน URL นั้นตามต้องการด้วยตนเอง ตัวอย่างเช่นหากคุณต้องการเปลี่ยนชื่อโฮสต์จาก "abcxyz.com" เป็น "a111b222.com" คุณสามารถแก้ไขได้โดยพิมพ์ ...

'cfzhttp://a111b222'

.. นี่เป็นเพียงหนึ่งในหลาย ๆ วิธีในการแก้ไข ตรวจสอบให้แน่ใจว่าเป็นการแก้ไขโหมดปกติไม่ใช่การแก้ไขโหมดคำสั่ง

จากนั้นคุณจะไปที่เหตุการณ์ถัดไป ('n')

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

เมื่อคุณพิมพ์จำนวนเต็มขนาดใหญ่แล้ว - อย่ากด ENTER - กด F8 (หรือคีย์ใดก็ตามที่คุณกำหนดมาโครให้)

การดำเนินการนี้จะเปลี่ยนรูปแบบที่เกิดขึ้นทุกครั้งเหมือนกับที่คุณทำด้วยตนเองสำหรับเหตุการณ์แรก

ข้อสันนิษฐานอย่างหนึ่งของการแมปของฉันสมมติคือเมื่อคุณกด F8 เป็นครั้งแรกคุณจะอยู่ในตำแหน่งของไฟล์ในตำแหน่งที่คุณต้องการให้ทำการเปลี่ยนแปลงครั้งแรก

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

ดังนั้นอีกครั้งแนวคิดก็คือคุณทำการเปลี่ยนแปลงด้วยตนเองเพียงครั้งเดียว - ไม่สำคัญหากคุณเปลี่ยนคำ 5 คำครึ่งบรรทัด 7 บรรทัด ... ตัวดำเนินการแก้ไขซ้ำสุดท้ายจะจำสิ่งนี้ได้

จากนั้นคุณค้นหาเหตุการณ์ถัดไปที่จะเปลี่ยนแปลงตรวจสอบให้แน่ใจว่าเคอร์เซอร์อยู่ในตำแหน่งที่เหมาะสม (เช่นหากคุณกำลังเปลี่ยน URL ทั้งหมดตรวจสอบให้แน่ใจว่าเคอร์เซอร์อยู่ที่จุดเริ่มต้นของ "http: //" แทนที่จะอยู่ใน ตรงกลางของ URL) จากนั้นกด 10000F8

เปลี่ยนจำนวนเต็มให้สูงขึ้นหากคุณมีเหตุการณ์มากกว่า 10,000 ครั้ง

ข้อเสียคือประสิทธิภาพ แต่นั่นจะกลายเป็นปัญหาเมื่อคุณมีการแก้ไขจำนวนมากอย่างแท้จริง (สำหรับฉันการเปลี่ยนแปลงมากกว่า 10,000 รายการอาจช้า แต่ก็พอทนได้มากกว่า 100,000 รายการอาจใช้เวลานานมากและขอแนะนำให้เปลี่ยนกลับไปที่: s - แต่ระยะทางของคุณอาจ แตกต่างกันไป)

ข้อเสียอีกอย่างตามที่คนอื่นชี้ให้เห็นคือฉันไม่ได้ใช้สัญลักษณ์แทนแม้ว่าฉันจะหนีไปแล้วก็ตาม แต่การค้นหาสิ่งที่ต้องใช้สัญลักษณ์แทนนั้นง่ายมากหากset incsearchอยู่ใน vimrc ของคุณ คุณลักษณะนี้จะไฮไลต์ข้อความที่ตรงกันเมื่อคุณพิมพ์รูปแบบการค้นหาของคุณ เมื่อข้อเสนอแนะสดหยุดเน้นสิ่งใด ๆ คุณจะรู้ว่ารูปแบบของคุณไม่ถูกต้องซึ่งมักเกิดจากอักขระที่ต้องใช้ Escape ฉันชอบแทนที่อักขระด้วย "." เป็นตัวยึดตำแหน่งที่จับทั้งหมด (เพียงเพราะฉันคิดว่ามันง่ายกว่าที่จะพิมพ์ แต่การใช้ Escape ก็ใช้ได้เช่นกัน)

husB Aug 24 2020 at 15:44

การใช้งานและการทำซ้ำกับcgn.

  • ขั้นแรกค้นหาสตริง "เก่า" ด้วย/.

  • cgnถัดไปตี สิ่งนี้จะแทนที่เหตุการณ์ถัดไปของ 'old' และทำให้คุณอยู่ในโหมดแทรก

  • พิมพ์ข้อความแทนที่ 'ใหม่' และกดEscเมื่อเสร็จสิ้น

  • ทำซ้ำสำหรับเหตุการณ์อื่น ๆ ทั้งหมดของ 'เก่า' [count].ด้วย

แนวคิดคือการพิมพ์สตริงการแทนที่ 'ใหม่' ในโหมดการแทรกที่ดีเพื่อที่เราจะได้ไม่ต้องกังวลกับการหลีกเลี่ยงอักขระพิเศษ

สำหรับ[count]จำนวนมาก ๆ จะเพียงพอ หรือหาจำนวนของการเกิดขึ้นของ 'เก่า' :%sgnกับ

(สำหรับอักขระพิเศษใน 'old' สิ่งที่ดีที่สุดที่ฉันคิดได้คือ/\V<old>คุณยังคงต้องหนี\และ/อย่างไรก็ตาม)