วิธีเพิ่มหมายเลขบรรทัดถาวรในไฟล์ได้อย่างไร


21

ฉันมีไฟล์ข้อความเช่นนี้ (ใช้ gVim บน Windows)

foo bar baz quux 
corge grault garply 
waldo fred plugh 
[...150 more lines...]
xyzzy thud

ฉันต้องการเพิ่มตัวเลขในแต่ละบรรทัดในไฟล์ ไม่ได้ใช้:set numberแต่เพิ่มหมายเลขเป็นข้อความนำหน้าแต่ละบรรทัดดังนี้ดังนั้นหมายเลขจึงเป็นส่วนหนึ่งของไฟล์

1. foo bar baz quux 
2. corge grault garply 
3. waldo fred plugh 
[...~150 more lines...]
155. xyzzy thud

awkอาจเป็นเครื่องมือสำหรับงานนี้ แต่ฉันอยู่บน Windows (ถอนหายใจ)
roblogic

ตอบที่นี่แล้วไม่เคยคิด :)
roblogic

1
บางที .. หรือว่านี่เป็นเรื่องทั่วไปมากกว่านี้ใช่ไหม
muru

มันคล้ายกัน แต่ฉันไม่รู้ว่าหมายเลขบรรทัดถาวรคืออะไร คำถามที่สองคือคำถามเกี่ยวกับทุกบรรทัด (และคำตอบคือ) สำหรับ gVim บน Windows โดยเฉพาะและนี่คือรายการหมายเลขที่เรียบง่ายสำหรับหนึ่งย่อหน้าใน vim ธรรมดาเท่านั้น
kenorb

3
ฉันเดาว่าโพสต์นั้นใช้ "ถาวร" ot ระบุว่าจะต้องแก้ไขบัฟเฟอร์และตัวเลขนั้นไม่ใช่สิ่งที่เห็นได้ชัด (เหมือนกับคุณ) เหตุผลในการระบุ gvim บน Windows คือการหลีกเลี่ยงยูทิลิตีภายนอกเช่นcatหรือnlซึ่งสามารถทำตัวเลขบรรทัดได้ แต่โดยทั่วไปจะไม่สามารถใช้งานได้บน Windows (ตามที่ OP ระบุจากความคิดเห็นของพวกเขาawk) โซลูชันสองอันดับแรกเป็นกลุ่มบริสุทธิ์ สุดท้ายเส้นทั้งหมดเทียบกับหนึ่งพาราเป็นเพียงเรื่องของการเลือกช่วง เห็นได้ชัดว่าไม่ใช่เรื่องใหญ่
muru

คำตอบ:


36

ในกลุ่มแฟชั่นบริสุทธิ์:

:%s/^/\=line('.').". "

คำอธิบาย:

:%s/^/            " the substitution will be applied to the beginning of every line
\=                " the rest of the replacement part is an expression
line('.').". "    " the expression returns the current line number concatenated with a dot and a space

ดูและ:help \=:help line()

การใช้นิพจน์ในส่วนทดแทนนั้นมีประสิทธิภาพมากและ FWIW เป็นจุดเริ่มต้นที่ดีสำหรับ vimscript


ฉันจะเพิ่มคำสั่งที่มีประโยชน์มากนี้ให้กับ keymap ใน vimrc ได้อย่างไร?
cosmicraga

หากต้องการไปที่หัวข้อวิธีใช้สำหรับการทดแทน::help sub-replace-expression
akurtser

9

สิ่งหนึ่งที่ดีเกี่ยวกับแมโคร Vim คือพวกเขาสามารถเรียกคืนได้ (สามารถเรียกใช้ตัวเองได้):

  1. ล้างการลงทะเบียน q: qqq
  2. เพิ่มหมายเลขในบรรทัดแรก: ggI1.(อย่าลืมที่ว่าง!)
  3. เลื่อนกลับไปที่จุดเริ่มต้นและเริ่มบันทึกแมโคร: 0qq
  4. คัดลอกหมายเลข: yW
  5. เลื่อนลงบรรทัดแล้ววางตัวเลข: +P
  6. ย้ายกลับไปที่จุดเริ่มต้นของบรรทัดและเพิ่มจำนวน: 0<c-a>
  7. ย้ายกลับไปที่จุดเริ่มต้นของบรรทัด (เพื่อให้แมโครไม่แตกเมื่อได้รับเป็นตัวเลขสองเท่า!): 0
  8. เรียกแมโครครั้งเดียวเพื่อทำให้มันวนซ้ำ ณ จุดนี้ยังไม่มีอะไรใน register q ดังนั้นจะไม่มีอะไรเกิดขึ้น: @q.
  9. บันทึกแมโคร: q
  10. เรียกมาโครอีกครั้งแล้วดูการบินของประกายไฟ: @@

แมโครจะเรียกใช้ตัวเองต่อไปจนกว่าจะถึงจุดสิ้นสุดของไฟล์

คุณสามารถใช้เคล็ดลับแมโครแบบเรียกซ้ำสำหรับปัญหาอื่น ๆ ที่คล้ายกันมากมายดังนั้นจึงเป็นเรื่องที่ควรระวัง

หากคุณไม่ต้องการใช้แมโครแบบเรียกซ้ำด้วยเหตุผลบางอย่างคุณสามารถข้ามขั้นตอนที่ 1 และ 8 และใช้จำนวนเพื่อเรียกใช้แมโครหลาย ๆ ครั้งเช่น100@qจะเรียกใช้แมโครq100 ครั้ง


1
สิ่งที่ทรงพลังฉันกราบไหว้ความเชี่ยวชาญของคุณ มาโครเป็นเหมือน
ศาสตร์

1
@ropata แมโครเป็นลำดับของคำสั่งโหมดปกติ (ส่วนใหญ่) เท่านั้น
romainl

1
@romainl ฉันคิดว่ามันจะดีกว่าที่จะคิดว่ามันเป็นลำดับของการกดแป้นพิมพ์
รวย

2
@ ริชมันสามารถเป็นลำดับของหลายสิ่งรวมถึงคำสั่ง ex
romainl

2
@ ฉีดใช่นั่นเป็นเหตุผลว่าทำไมฉันถึงคิดว่ามันเป็นการกดแป้นพิมพ์ที่ดีที่สุด มันเล่นทุกอย่างที่คุณพิมพ์บนคีย์บอร์ด (รวมถึงอย่างที่คุณพูดคำสั่ง ex) ราวกับว่าคุณพิมพ์ด้วยตนเองทั้งหมด
รวย

7

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

ก่อนอื่นเลือกพิสัยของคุณ (เส้นไหนที่คุณต้องการใช้สิ่งนี้) ฉันมักจะใช้เครื่องหมาย (เช่นmaในบรรทัดแรกและmbที่สอง แต่คุณยังสามารถใช้หมายเลขบรรทัดหรือการเลือกภาพ) จากนั้นป้อนการแก้ไขคำสั่งต่อไปนี้ (ปัจจุบันปรับแต่งสำหรับกรณีการใช้งานของคุณ)

:let i=1|'a,'bg/^/s/^/\=i.". "/|let i=i+1

โครงสร้าง

:let i=1

สิ่งนี้จะตั้งค่าตัวแปรiด้วยค่าเริ่มต้น โดยปกติรายการเริ่มต้นด้วย 1 ดังนั้นฉันจึงตั้งค่า i เป็น 1

|

แถบเริ่มคำสั่งใหม่

'a,'b

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

g/^/

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

Item some txt
other text

Item second item
whatever
Item third

และต้องการวางป้ายกำกับเหล่านี้ไว้ด้านหน้าItemและละเว้นบรรทัดอื่นให้ทำg/Item/หรือg/^Item/แทน (สมมติว่าข้อความรายการตามตัวอักษร)

s/^/\=i.". "/

นี้ดำเนินการแสดงออกปกติเพื่อแทนที่จุดเริ่มต้นของเส้นที่มีค่าของการตัดแบ่งด้วยi .โดยทั่วไปคุณสามารถทำสิ่งนี้ได้ (แทนที่ฉลากItemด้วยหมายเลขเป็นต้น)

|let i=i+1

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


7

เพิ่มตัวเลขให้กับทุกบรรทัด

เป็นไปได้ที่จะใช้:%!nl -baหรือ:%!cat -nคำสั่งที่จะเพิ่มหมายเลขบรรทัดในทุกบรรทัด

บน Windows คุณต้องติดตั้ง Cygwin / MSYS / SUA

เพิ่มตัวเลขในบรรทัดที่เลือก

ในการเพิ่มตัวเลขสำหรับบรรทัดที่เลือกเท่านั้นโปรดเลือกในโหมดภาพ ( vและเคอร์เซอร์) จากนั้นเมื่อเสร็จแล้ว - ดำเนินการคำสั่ง: :%!nl(ไม่สนใจบรรทัดว่าง) หรือ:%!cat -n(รวมบรรทัดว่าง)

การจัดรูปแบบ

หากต้องการลบช่องว่างเพิ่มเติมให้เลือกพวกเขาในบล็อกภาพ ( Ctrl+ v) และลบออก ( x)

หากต้องการเพิ่มตัวละครบางตัว ( ., :, )) หลังจากตัวเลขที่เลือกไว้ในบล็อกภาพ ( Ctrl+ v) แล้วผนวกตัวอักษร ( Aพิมพ์ตัวอักษรแล้วจบด้วยEsc)


2
สิ่งนี้ไม่ได้จัดรูปแบบเหมือนกับที่กำหนดในคำถาม อย่างไรก็ตามฉันชอบความเรียบง่ายของการแก้ปัญหา
Karl Yngve Lervåg

@ KarlYngveLervågขอบคุณรวมอยู่ในคำตอบด้วย
kenorb

5

การแก้ไขคำตอบของ romainl :

:%s/^\(\d\+\. \)\?/\=line('.').". "

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

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

ส่วนที่เพิ่ม:

  • ^ - จุดเริ่มต้นของบรรทัด
  • \( - เริ่มกลุ่มย่อยใหม่
  • \d\+ - จับคู่ตัวเลขหนึ่งครั้งหรือมากกว่า
  • \. - ตรงจุด ( .) และพื้นที่
  • \) - สิ้นสุดกลุ่มย่อย
  • \? - ทำให้กลุ่มเป็นตัวเลือกเพื่อให้ทำงานได้เหมือนก่อนหน้าถ้ายังไม่มีหมายเลขในบรรทัดนี้

คำใบ้โบนัส:
หากต้องการลบหมายเลขบรรทัดคุณสามารถใช้รูปแบบเดียวกันกับส่วน repalce ที่ว่างเปล่า:

:%s/^\(\d\+\. \)\?//

5
I1. <esc>^qqyWjP^<C-a>q

จำนวนนี้เป็นสองบรรทัดแรกและคุณสามารถกด@qเพื่อนับจำนวนบรรทัดถัดมา (หรือพิมพ์ ex. 18@qหากคุณต้องการรวมจำนวน 20 บรรทัด)

คำอธิบาย:

I1. <esc>  Number the first line
hqq        Go back to the start of the line and start recording a macro
yWjP       Copy the line number to the next line
^<C-a>     Increment the next line's line number
q          Finish recording

ประโยชน์ของสิ่งนี้คือมันไม่จำเป็นต้องใช้คำสั่งภายนอกใด ๆ ซึ่งมีประโยชน์หากคุณทำงานกับ Vim บน Windows เป็นต้น


หลังจากพิมพ์1. <esc>hคุณอยู่ในคอลัมน์ที่สองไม่ใช่คอลัมน์แรก ฉันจะแทนที่hด้วย0หลังจากนั้นฉันคิดว่าวิธีแก้ปัญหาของคุณควรจะดีมาก
Karl Yngve Lervåg

@ KarlYngveLervågอ๊ะนั่นเป็นคำที่สะกดผิด ขอบคุณแก้ไข
ลูกบิดประตู

ไม่มีปัญหา. อย่างไรก็ตามคุณยังไม่ได้อัปเดตคำอธิบาย นอกจากนี้: บนแป้นพิมพ์หลาย ๆ ตัวให้^รออักขระตัวที่สองเพื่ออนุญาตให้พิมพ์ค่าผสมเช่น^a -> âรอให้ตัวละครที่สองเพื่อให้อยู่รวมกันเช่นการพิมพ์ฉันยังเห็นด้วยกับวิธีที่ดีที่สุด แต่ฉันคิดว่าควรพูดถึงเช่นกัน
Karl Yngve Lervåg

3

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

:%!cat -n

การทำเช่นนี้จะกรองบัฟเฟอร์ทั้งหมดของคุณ (ตามที่แสดงโดย%) ผ่านโปรแกรมภายนอกcatโดยที่-nแฟล็กเป็นการเตรียมอินพุตแต่ละบรรทัดด้วยหมายเลขบรรทัด

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

ดู:help :range!รายละเอียดเพิ่มเติมเกี่ยวกับการกรองผ่านโปรแกรมภายนอก


1
ฉันรู้ว่าผู้ถามใช้ gVim บน Windows ดังนั้นโซลูชันนี้อาจไม่ทำงานที่นั่น อย่างไรก็ตามฉันคิดว่ามันยังให้โอกาสผู้อื่นได้เรียนรู้จากมัน
tommcdo

หากคุณติดตั้งmsysgitและเพิ่มลงใน PATH ของคุณ (IIRC เป็นตัวเลือกการติดตั้ง) โซลูชันนี้ควรทำงานบน Windows
Martin Tournoij

4
cat -nไม่ใช่ POSIX แต่nlเป็นดังนั้นจึงอาจเป็นตัวเลือกที่ดีกว่า
muru

2

วิธีการแฮ็กบิตอาจเป็นดังต่อไปนี้ (ทุกสิ่งที่เขียนระหว่าง <และ> จะถูกแทรกหลังจากกดCtrl+ v):

:%normal :redir @"<Enter>:-=<Enter>:redir END<Enter>I<C-R>".<Tab><Esc>kdd

โครงสร้าง

:%normal {commands}

รันคำสั่งโหมดปกติในแต่ละบรรทัดที่ระบุโดยช่วงในกรณีนี้ทุกบรรทัด

:redir @"

เปลี่ยนเส้นทางทุกเอาต์พุตที่ทำโดยคำสั่ง ex ไปยังบัฟเฟอร์ที่ไม่มีชื่อ

:.=

เป็นคำสั่ง ex ที่ส่งออกหมายเลขบรรทัดปัจจุบัน (ด้วยการขึ้นบรรทัดใหม่ก่อนหน้านี้น่าเสียดาย)

:redir END

หยุดการเปลี่ยนเส้นทางไปยังบัฟเฟอร์ที่ไม่มีชื่อ

I<C-R>".<Tab><Esc>

แทรกเนื้อหาของบัฟเฟอร์ที่ไม่มีชื่อด้วย a และแท็บไปด้านหน้าของแต่ละบรรทัดและออกจากโหมดแทรก

kdd

ไปหนึ่งบรรทัดและลบบรรทัดใหม่ซึ่งเป็นผลลัพธ์ของคำสั่ง:. =

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