คล้ายกับคำตอบที่https://vi.stackexchange.com/a/818/227คุณสามารถใช้คำสั่งโกลบอล
ด้วยคุณสามารถสั่งให้เป็นกลุ่มเพื่อค้นหาบรรทัดที่ตรงกับรูปแบบแล้วดำเนินการคำสั่งกับมัน
ในกรณีของคุณคุณต้องการเพิ่มข้อความลงในบรรทัดที่ขึ้นต้นด้วย "ระดับ N:" ดังนั้นคำสั่งทั่วโลกของเราอาจเป็นได้
:g/^Level \d:/{COMMANDS}
การใช้คำสั่ง replace (การแทนที่นิพจน์ปกติ) สำหรับคำสั่ง
คำสั่งนั้นสนุกกว่า ฉันมักจะต้องการเปลี่ยนนิพจน์ปกติสำหรับสิ่งเช่นนี้เนื่องจากมันง่ายต่อการใช้ตัวแปร
ตัวอย่างคำถามของคุณ
:let i = 1 | g/^Level \d:/s/^/\=printf("%02d ", i)/ | let i = i+1
มันทำงานอย่างไร
ในส่วนการแทนที่ของคำสั่งการทดแทนสามารถเป็นนิพจน์
สิ่งแรกที่เราจะทำคือตั้งค่าตัวแปรi
ให้เป็นหมายเลขเริ่มต้น ฉันเลือก 1 แต่หมายเลขใด ๆ ที่จะทำlet i = 1
จากนั้นเราก็เรียกใช้คำสั่งระดับโลกของเราซึ่งกำหนดให้เราดำเนินการในบรรทัดที่ตรงกัน g/^Level \d:/
เราจะให้คำสั่งระดับโลกของเราแทรกค่าและเพิ่มตัวนับของเราโดยใช้คำสั่งการแทนที่และคำสั่ง lets/^/\=printf("%02d ", i)/ | let i = i+1
นิพจน์ปกติของคำสั่งการแทนที่ค้นหาจุดเริ่มต้นของบรรทัด^
และแทนที่ด้วยนิพจน์และนิพจน์ของเราจะเป็นผลลัพธ์ของการพิมพ์ที่จัดรูปแบบ เช่นเดียวกับในภาษา C printf ของ vim ใช้การจัดรูปแบบพารามิเตอร์ %02d
วิธีการแปลงข้อโต้แย้งราวกับว่ามันเป็นตัวเลขทศนิยมd
ครอบครองอย่างน้อย 2 คัน2
และแผ่นด้วย 0
0 สำหรับรายละเอียดและตัวเลือกการแปลงอื่น ๆ (รวมถึงการจัดรูปแบบจุดลอย) :help printf
ดู เราให้ตัวแปรการนับของเรา printf i
และมันให้เรา01
เป็นครั้งแรกครั้ง02
ที่สอง ฯลฯ สิ่งนี้ถูกใช้โดยคำสั่งการแทนที่เพื่อแทนที่จุดเริ่มต้นของบรรทัดการแทรกผลลัพธ์ของ printf ที่จุดเริ่มต้นได้อย่างมีประสิทธิภาพ
โปรดทราบว่าฉันใส่ช่องว่างหลังจาก "%02d "
D: คุณไม่ได้ถามคำถาม (และฉันไม่เห็นตัวอย่างผลลัพธ์) แต่ฉันสงสัยว่าคุณต้องการแยกตัวเลขออกจากคำว่า "ระดับ" ลบช่องว่างออกจากสายอักขระที่กำหนดให้ printf เพื่อให้มีหมายเลขแทรกอยู่ข้าง L ในระดับ
ท้ายที่สุดนั่นเป็นการlet i = i + 1
เพิ่มตัวนับของเราหลังจากการเปลี่ยนตัวแต่ละครั้ง
สิ่งนี้สามารถนำไปใช้โดยทั่วไปเพื่อแทนที่ส่วนต่าง ๆ ของเส้นที่ถูกจับคู่โดยเกณฑ์อื่นด้วยข้อมูลการทำงานโดยพลการ
ใช้คำสั่งปกติรวมกัน
สิ่งนี้ดีสำหรับการแทรกแบบง่ายหรือการแก้ไขที่ซับซ้อน เช่นเดียวกับการแทนที่เราจะใช้การจับคู่แบบโกลบอล แต่แทนที่จะใช้การแทนที่นิพจน์ทั่วไปเราจะดำเนินการชุดของการดำเนินการราวกับว่าพิมพ์โดยผู้ใช้
ตัวอย่างคำถามของคุณ
:let i = 1 | g/^Level \d:/execute "normal! I" . printf("%02d ", i) | let i = i+1
มันทำงานอย่างไร
ค่าที่ใช้นั้นคล้ายกับตัวทดแทน (เรายังคงใช้ printf เพื่อจัดรูปแบบหมายเลขของเราเพื่อให้เป็น 0 padded ด้วยตัวเลข 2 หลัก) แต่การดำเนินการแตกต่างกัน
ที่นี่เราใช้คำสั่ง execute ซึ่งรับสตริงและรันสตริงเป็นคำสั่ง ex ( :help :exe
) เราสร้างสตริงที่รวม "ปกติ! ฉัน" กับข้อมูลของเราซึ่งจะเป็น "ปกติ! I01" ในครั้งแรกและ "ปกติ! I02" ครั้งที่สอง ฯลฯ
normal
การดำเนินงานคำสั่งดำเนินการเช่นถ้าในโหมดปกติ ในตัวอย่างนี้คำสั่งปกติของเราคือI
ซึ่งแทรกที่จุดเริ่มต้นของบรรทัด ถ้าเราใช้dd
มันจะลบบรรทัดo
จะเปิดบรรทัดใหม่หลังจากบรรทัดที่ตรงกัน มันเหมือนกับว่าคุณพิมพ์I
(หรือปฏิบัติการอื่น ๆ ) ตัวเองในโหมดปกติ เราใช้!
after normal
เพื่อให้แน่ใจว่าไม่มีการแมปเข้ามาในทางของเรา :help :normal
ดู
สิ่งที่ใส่เข้าไปแล้วคือค่าของ printf ของเราดังเช่นในตัวอย่างแรกของการใช้ทดแทน
วิธีการนี้จะมีนักเล่นกว่า regex เพราะคุณสามารถทำสิ่งที่ต้องการexecute "normal! ^2wy" . i . "th$p"
ซึ่งจะไปที่จุดเริ่มต้นของข้อความ^
ก้าวไปข้างหน้า 2 คำ2w
งัดจนบอด 'H' ตัวละครy" . i . "th
ย้ายไปยังจุดสิ้นสุดของเส้นและวาง$
p
นี่เป็นเหมือนการเรียกใช้แมโคร แต่ไม่ได้ใช้การลงทะเบียนและสามารถรวมสตริงจากนิพจน์ใด ๆ ฉันพบว่าสิ่งนี้มีพลังมาก
วิธีการที่แต่ละระดับมีเคาน์เตอร์ของตัวเอง
คุณอาจต้องการแต่ละระดับเพื่อรับตัวนับของตนเอง หากคุณทราบจำนวนสูงสุดของระดับล่วงหน้าคุณสามารถทำสิ่งต่อไปนี้ได้ (เพิ่มรหัสพิเศษเพื่อค้นหาระดับที่ใหญ่ที่สุดอาจไม่ยากเกินไป แต่จะทำให้คำตอบนี้ยาวเกินไป
ก่อนอื่นให้ฟรี i ในกรณีที่เราใช้มันเป็นจำนวนเต็ม เราไม่สามารถแปลง i เป็นรายการเราต้องสร้างมันขึ้นมาแบบนั้น
:unlet! i
ถัดไปให้ตั้งเป็นรายการที่มีจำนวนระดับ คุณแสดงคำถาม 2 ข้อ แต่ให้สมมติ 10 เพื่อความสนุก เนื่องจากการจัดทำดัชนีรายการเป็นแบบ 0 และฉันไม่ต้องการแก้ไขการเรียงลำดับแบบ 1 เช่นรายการของคุณเราจะสร้างองค์ประกอบมากพอ (11) และไม่เคยใช้ดัชนี 0
:let j = 0
:let i = []
:while j < 11 | let i += [1] | let j += 1 | endwhile
ต่อไปเราต้องการวิธีในการรับหมายเลขระดับ โชคดีที่มีฟังก์ชั่นทดแทนเป็นฟังก์ชั่นเช่นกันดังนั้นเราจะให้สายของเราและแยกหมายเลขระดับsubstitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")
เนื่องจากฉันเป็นรายการ 11 1
วินาที (แต่ละดัชนีเป็นตัวนับสำหรับระดับของเรา) ตอนนี้เราสามารถปรับตัวอย่างใดตัวอย่างหนึ่งข้างต้นเพื่อใช้ผลลัพธ์ของการทดแทนนี้:
ผ่านคำสั่งทดแทน:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | s/^/\=printf("%02d ", i[ind])/ | let i[ind] += 1
ผ่านคำสั่งปกติ:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | execute "normal! I" . printf("%02d ", i[ind]) | let i[ind] += 1
อินพุตตัวอย่าง:
Level 1: stuff
Level 1: Stuff
Some text
Level 3: Other
Level 1: Meh
Level 2: More
ตัวอย่างผลลัพธ์:
01 Level 1: stuff
02 Level 1: Stuff
Some text
01 Level 3: Other
03 Level 1: Meh
01 Level 2: More