ลบ n lines ข้าม 1 สคริปต์บรรทัด


10

ฉันต้องการสร้างสคริปต์ Vim พื้นฐานที่เพียงแค่ลบบรรทัด n ข้าม 1 บรรทัดและทำซ้ำจนกว่าจะสิ้นสุดของเอกสาร ฉันไม่สนใจการจับคู่ที่เฉพาะเจาะจงฉันแค่ต้องการลบบรรทัด ตัวอย่างเช่น; ดังนั้นฉันต้องการทำซ้ำคำสั่ง3ddjสำหรับเอกสารทั้งหมด

Text I want to keep.   
Text I want to delete.  
Text I want to delete.  
Text I want to delete.  
Text I want to keep.  
Text I want to delete.  
Text I want to delete.  
Text I want to delete.  
Text I want to keep.  
Text I want to delete.  
Text I want to delete.  
Text I want to delete.   

ดังนั้นดูเหมือน ...

Text I want to keep.  
Text I want to keep.  
Text I want to keep.  

ขอบคุณ.


คุณรวมแท็กregular-expressionไว้ในคำถามของคุณ แต่ดูเหมือนว่าคำถามจะไม่ระบุเหตุผลในการทำสิ่งนี้ด้วยนิพจน์ทั่วไป หากคุณกำลังมองหาบางสิ่งที่ใช้นิพจน์ทั่วไปstackoverflow.com/questions/17735289/…อาจเป็นที่สนใจ คำถามนั้นเกี่ยวกับ Notepad ++ แต่คำตอบไม่ได้ใช้อะไรนอกจาก regre pcre (ข้อสงวนสิทธิ์: ฉันเขียนคำตอบนั้น)
Jasper

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

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

คำตอบ:


19

วิธีการง่ายมาก:

  1. ย้ายไปที่บรรทัดแรกที่คุณต้องการลบ
  2. บันทึกแมโคร: qa3ddjq
  3. ทำซ้ำโดยใช้ตัวเลขสูง: 1,000 @ a

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

:help recordingดู


2
ที่น่าตื่นตาตื่นใจ!!! ขอบคุณมากที่ได้ผลกับฉัน: D
Max Copley

1
คำอธิบาย: q(ในโหมดคำสั่งและในกลุ่มหรือเวอร์ชันสำรองอื่นล่าสุด [neovim ฯลฯ ] แต่ไม่ใช่ใน vi ต้นฉบับ) หมายถึง "เริ่มการบันทึกและวางไว้ในบัฟเฟอร์ 'จดหมายถัดไป' ดังนั้น: qaหมายถึง "เริ่มการบันทึกลงในบัฟเฟอร์ 'a' จากนั้นทุกปุ่มที่พิมพ์หลังจากนี้ (จนกระทั่งถัดไปqในโหมดคำสั่ง) จะถูกบันทึกไว้ (คุณสามารถบันทึกได้: เข้าสู่โหมดแก้ไข, พิมพ์อะไรบางอย่าง, หนีไปยังโหมดคำสั่ง ฯลฯ ) จากนั้น12@aจะทำซ้ำการกระทำใด ๆ ที่บันทึกไว้ในบัฟเฟอร์ "a" 12 ครั้ง
Olivier Dulac

3
นอกจากนี้หากคุณไม่ต้องการเรียกใช้บางสิ่งบางอย่าง1000@qในตอนท้ายคุณสามารถสร้างมาโครแบบเรียกซ้ำqa3ddj@aq@aได้แม้ว่าคุณอาจต้องทำqaqก่อนเพื่อให้แน่ใจว่ามีการ"aเริ่มต้นว่างเปล่า
James

17

ทางออกที่ง่ายที่สุดสำหรับฉันคือ:

:%norm j3dd

นั่นคือ:

  • %: สำหรับทุกบรรทัด
  • norm: เรียกใช้ปุ่มต่อไปนี้ราวกับว่าอยู่ในโหมดปกติ
  • j3dd: ไปที่บรรทัดแล้วลบ 3 บรรทัด

ดังนั้นจากบรรทัดแรกไปที่บรรทัดที่สองและลบ 3 บรรทัดถัดไป ที่สองText I want to keep.คือตอนนี้ในบรรทัดที่สอง ลงหนึ่งบรรทัดลบ 3 ล้างแล้วทำซ้ำ


หมายเหตุ: หากคุณไม่ต้องการประมวลผลไฟล์ทั้งหมดคุณสามารถแทนที่%normด้วยเช่น5,$normเพื่อดำเนินการจากบรรทัดที่ 5 ถึงตอนท้ายของไฟล์


4
ทางเลือกที่ดีมาก! ทำงานเป็นกลุ่ม (ไม่ใช่ vi) ฉันไม่เคยได้ยินเรื่อง "บรรทัดฐาน" มาก่อน! (และผมชนิดของ vi [M] geek)
โอลิเวีย Dulac

6

คุณมีโซลูชันที่ยอดเยี่ยมที่มีอยู่แล้ว นี่คืออีกหนึ่ง:

:g/^/if line('.')%4!=1|:s/^/DELETE ME/|endif
:g/^DELETE ME/d

ครั้งแรกที่เราดำเนินการในทุกบรรทัด ( :gการจับคู่กับ^(จุดเริ่มต้นของบรรทัด)) linenumber % 4และหมายเลขทุกบรรทัดดำเนินการผลมาจากการ หากผลลัพธ์ไม่เท่ากัน1เราจะเพิ่มDELETE MEที่จุดเริ่มต้นของบรรทัดทำเครื่องหมายบรรทัดที่จะลบโดยคำสั่งถัดไป

คำสั่งถัดไปเป็นคำสั่งปกติ ( :g) ที่ตรงกับทุกบรรทัดที่ขึ้นต้นด้วยDELETE MEและทำเช่นนั้น

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


4

ฉันรู้ว่านี่คือviช่องทาง แต่สำหรับฉันแล้วนี่เป็นsedปัญหา

sed -ne 'p;n;n;n' <file >newfile

เพื่อให้คุณสามารถโต้กลับเป็นviโซลูชัน:

:0
!Gsed -ne 'p;n;n;n'

1
+1 สำหรับวิธีการแก้ปัญหา
Christian Brabandt

3

อีกทางเลือกหนึ่ง (ฉันสมมติว่าเราเริ่มต้นในบรรทัดที่ 1 และลบบรรทัด 2-4, 6-8 และอื่น ๆ ตามข้อความตัวอย่าง):

while line(".") < line("$")
    silent +1delete _ 3
endwhile

หากต้องการทำสิ่งนี้แบบโต้ตอบคุณสามารถใช้ "command-line register" นั่นคือกด

:+1del 3<CR> แล้ว 1000@:


1

ทางเลือก: คุณต้องการเก็บบรรทัดใด ๆ : 1, 4, ฯลฯ คุณสามารถใช้:

awk '!((FNR-1)%3)'  file > newfile
      # awk: when a condition is given without action:
      #        prints the lines for which the condition returns 0.
      # FNR designates the line number in the current file.
      # a%3 : takes the modulus of a and 3. ( 0%3=0, 1%3=1, 2%3=2, 3%3=0, 4%3=1, etc.) 
      # This will be 0 for 3, 6, etc. 
      # But we want it to be 0 (true) for 1, 4, etc : so we substract 1 to NR

# to see that it keeps those lines:
seq 1 20 | awk '!((NR-1)%3)'
1
4
7
10
13
16
19

ทางเลือกอื่น: หากคุณรู้ว่าบรรทัดที่คุณต้องการตรงกับรูปแบบที่ไม่ซ้ำกัน:

# for exemple each line you want contains "some pattern":
fgrep "some pattern" file > newfile
# (or regular grep if you want "some pattern" to be interpreted as a regexp)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.