Vim: s แทนที่ N <g แรกที่เกิดขึ้นในบรรทัด


13

ในกลุ่มบางครั้งผมมีโอกาสที่จะเปลี่ยนที่เกิดขึ้นไม่กี่แรกของการแข่งขันบนเส้น แต่ไม่เหมือนทุกgหากว่า เช่น:

a a a a a

ถึง

b b b a a

ฉันรู้ว่าฉันสามารถใช้งาน:s/a/b/[enter]:[up][enter]:[up][enter]ได้ แต่มันน่าเบื่อพอสำหรับการทำซ้ำสามครั้งฉันมีบรรทัดที่มีการแทนที่มากกว่า 10 รายการ
ฉันพยายามแล้ว:

  • :s/a/b/3g: เป็นกลุ่มบ่นของตัวอักษรต่อท้าย
  • :s/a/b/3: เปลี่ยนการเกิดขึ้นครั้งแรกในสิ่งนี้และสองบรรทัดต่อไปนี้
  • 3:s/a/b: เหมือนก่อนหน้านี้
  • :s/a/b/g3: เปลี่ยนสิ่งที่เกิดขึ้นทั้งหมดนี้และสองบรรทัดถัดไป
  • :3s/a/b: เปลี่ยนการเกิดขึ้นครั้งแรกในบรรทัดที่ 3
  • :/a/,3/a/s/a/b: การเปลี่ยนแปลงที่เกิดขึ้นครั้งแรกในแต่ละบรรทัดระหว่างบรรทัดถัดไปaและบรรทัดที่สามที่มีaอยู่ในไฟล์ (พร้อมท์ให้ย้อนกลับหากจำเป็น)
  • :/a/,/\([^a]*a\)\{3\}/s/a/b/: เปลี่ยนเหตุการณ์ที่เกิดขึ้นครั้งแรกในแต่ละบรรทัดระหว่างสิ่งนี้และสิ่งต่อไปด้วย 3 aวินาทีบนสิ่งนั้น

และรูปแบบการกำหนดแอดเดรสอื่น ๆ ที่หลากหลายซึ่งไม่ได้ผล ฉันต้องบอกว่าฉันได้เรียนรู้จำนวนพอสมควรเกี่ยวกับ:sคำสั่งที่พยายามค้นหาคำตอบสำหรับปัญหานี้ แต่ฉันยังไม่ได้แก้ไข

ใครรู้วิธีการทำเช่นนี้?

(คะแนนโบนัสสำหรับช่วงที่เฉพาะเจาะจงเช่นที่สองถึงเหตุการณ์ที่สี่)


2
ฉันค่อนข้างมั่นใจว่าคุณไม่สามารถทำเช่นนั้นได้ในกลุ่ม แต่เพื่อให้น่าเบื่อน้อยลงคุณรู้หรือไม่เกี่ยวกับ "n" และ " อยู่ในโหมดภาพ? นั่นคือคุณใช้ / pattern / เพื่อค้นหาสิ่งที่เปลี่ยนแปลงเปลี่ยนโดยใช้ "cw" หรืออะไรก็ตามใช้ "n" (แค่ n ไม่มีเครื่องหมายคำพูด) เพื่อค้นหารูปแบบและกด "ถัดไป (เพียงแค่ช่วงเวลาไม่มีคำพูด) เพื่อทำการแก้ไขครั้งล่าสุด
Bruce Ediger

@BruceEdiger ฉันรู้nและ.ถึงแม้ว่าฉันไม่ได้คิดที่จะใช้พวกเขาที่นี่ การปรับปรุงแน่นอนขอบคุณ
Kevin

s/a/=something/ควรทำเคล็ดลับ ( :help sub-replace-=) ฉันไม่คล่องพอที่ Vim จะเขียนsomethingออกมาทันที
Gilles 'หยุดชั่วร้าย'

หมายเหตุ: :[up][enter]สามารถแทนที่ด้วย&ซึ่งยังไม่เหมาะ แต่อย่างน้อยก็เจ็บปวดน้อยกว่า
Kowh

คำตอบ:


10

การสร้าง:s/pattern/replacement/gc แนวคิดจาก Samus_ (ซึ่งดูเหมือนจะเป็นวิธีที่ง่ายที่สุดในการตรวจสอบการทำงานที่ถูกต้องเมื่อมีรูปแบบอยู่ในสตริงการแทนที่) เพื่อแทนที่การเกิดเหตุการณ์ที่ 2 ถึง 4 ในบรรทัดเดียว:

:call feedkeys("nyyyq") | s/pat/string/gc

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

สำหรับกรณีทั่วไปให้แทนที่MthถึงNthบนบรรทัดเดียวสำหรับN ที่มากกว่าหรือเท่ากับM ที่มีขนาดใหญ่มาก:

:call feedkeys(repeat("n", M-1) . repeat("y", N-M+1) . "q") | s/pat/string/gc

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


อืมมม ฉันชอบอันนี้ ฉันควรจะสามารถเขียนฟังก์ชั่นสำหรับมันได้เช่นกัน
Kevin

8

สำหรับคำถามแรกฉันจะทำ:

:s/a/b
&&

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

:s/a/b/gc

จากนั้นคุณตอบกลับ "ไม่" ถึงการจับคู่ n แรกและ "ใช่" กับคนอื่น ๆ


อืมฉันลืมไปcแล้วว่าอาจเป็นทางออกที่ดีที่สุดที่เสนอ ฉันยังต้องนับ แต่ฉันคิดว่ามันเป็นตัวเลือกแรกที่จะทำงานกับการแทนที่ที่มีสตริงการค้นหา
เควิน

6
a a a a a
a a a a a
a a a a a
a a a a a
a a a a a
a a a a a
a a a a a

:3,6g/^/let i=0 | while i<3 | s/a/b/ | let i+=1 | endwhile

a a a a a
a a a a a
b b b a a
b b b a a
b b b a a
b b b a a
a a a a a

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

เรื่องของความงาม!
บิชอป

1

ฉันคิดว่ามันอาจใช้งานได้แทนที่ก่อนแล้วทำซ้ำ 2 ครั้ง:

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