Xóa n dòng bỏ qua 1 dòng script


10

Tôi muốn tạo một tập lệnh Vim cơ bản chỉ đơn giản là xóa n dòng, bỏ qua 1 dòng và lặp lại cho đến khi kết thúc tài liệu. Tôi không quan tâm đến các trận đấu cụ thể, tôi chỉ muốn xóa dòng. Ví dụ; Vì vậy, tôi muốn lặp lại lệnh 3ddjcho toàn bộ tài liệu.

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.   

Có vẻ như ...

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

Cảm ơn bạn.


Bạn đã bao gồm thẻ regular-expressionvào câu hỏi của bạn, nhưng câu hỏi dường như không chỉ định lý do để làm điều này với các biểu thức thông thường. Nếu bạn thực sự đang tìm kiếm thứ gì đó sử dụng các biểu thức thông thường, stackoverflow.com/questions/17735289/ mẹo có thể được quan tâm. Câu hỏi đó là về Notepad ++, nhưng câu trả lời không sử dụng gì ngoài regex pcre. (Tuyên bố miễn trừ trách nhiệm: Tôi đã viết câu trả lời đó.)
Jasper

Lần tới khi bạn hỏi một câu hỏi, không cần phải viết "Cảm ơn vì điều này. Giải pháp tuyệt vời!" trên mỗi câu trả lời Điều này thậm chí được viết ra khi bạn cố gắng tạo một nhận xét mới về một câu trả lời.
đường ống

Thêm vào đó, cách thích hợp để thể hiện sự đánh giá cao ở đây là chấp nhận câu trả lời phù hợp nhất với bạn và nêu lên bất kỳ câu trả lời nào bạn cho là hữu ích hoặc hữu ích. Mọi người sẽ thấy điều đó hơn là một bình luận "cảm ơn".
Lớp B

Câu trả lời:


19

Cách tiếp cận rất đơn giản:

  1. Di chuyển đến dòng đầu tiên bạn muốn xóa.
  2. Ghi lại một macro: qa3ddjq
  3. Lặp lại với số cao: 1000 @ a

Bước ba sẽ lặp lại macro một nghìn lần hoặc cho đến khi gặp lỗi. Đánh vào cuối tệp (do đó không có dòng nào để xóa) tạo ra lỗi và việc lặp lại macro bị hủy.

Xem :help recording.


2
Thật ngạc nhiên!!! Cảm ơn bạn rất nhiều, điều đó đã làm việc cho tôi: D
Max Copley

1
giải thích: q(trong chế độ lệnh và trong vim hoặc các phiên bản thay thế gần đây khác [neovim, v.v.), nhưng không phải trong vi gốc) có nghĩa là "bắt đầu ghi và đặt nó vào bộ đệm 'thư tiếp theo'. do đó: qacó nghĩa là "bắt đầu ghi vào bộ đệm 'a'. Sau đó, mọi phím được nhập sau này (cho đến lần tiếp theo qtrong chế độ lệnh) được ghi lại (bạn thậm chí có thể ghi: chuyển sang chế độ chỉnh sửa, đánh máy một cái gì đó, Thoát sang chế độ lệnh, v.v.). Sau đó 12@asẽ lặp lại bất cứ hành động nào được ghi lại trong bộ đệm "a" 12 lần.
Olivier Dulac

3
Ngoài ra, nếu bạn không muốn chạy một cái gì đó như 1000@qở cuối, bạn có thể tạo một macro đệ quy:, qa3ddj@aq@amặc dù bạn có thể cần phải làm qaqtrước để đảm bảo "abắt đầu trống.
James

17

Giải pháp đơn giản nhất với tôi sẽ là:

:%norm j3dd

Đó là:

  • %: cho mỗi dòng
  • norm: chạy các phím sau như thể ở chế độ bình thường
  • j3dd: đi xuống dòng sau đó xóa 3 dòng

Vì vậy, từ dòng đầu tiên, đi xuống dòng thứ hai và xóa 3 dòng tiếp theo. Thứ hai Text I want to keep.bây giờ là trên dòng thứ hai. Đi xuống một dòng, xóa 3. Rửa sạch và lặp lại.


Lưu ý: nếu bạn không muốn xử lý toàn bộ tệp, bạn có thể thay thế %normbằng ví dụ 5,$normđể xử lý từ dòng thứ 5 đến cuối tệp.


4
Thay thế rất tốt đẹp! Hoạt động trong vim (không vi). Tôi chưa bao giờ nghe về "định mức" trước đây! (và tôi thuộc loại vi [m] geek)
Olivier Dulac

6

Bạn có một số giải pháp tuyệt vời đã có sẵn. Đây là một cái nữa:

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

Đầu tiên, chúng tôi thực hiện một hành động trên mỗi dòng ( :gkhớp với ^(bắt đầu của dòng)) và với mỗi số dòng thực hiện kết quả của linenumber % 4. Nếu kết quả không bằng nhau 1, chúng tôi thêm DELETE MEvào đầu dòng, đánh dấu các dòng sẽ bị xóa bởi lệnh tiếp theo.

Lệnh tiếp theo là một lệnh thông thường ( :g), khớp với tất cả các dòng bắt đầu DELETE MEvà thực hiện.

Lưu ý, Bạn không thể xóa dòng ngay lập tức bằng :glệnh đầu tiên , vì điều này sẽ thay đổi phép tính modulo kết quả và do đó, trước tiên chúng ta phải đánh dấu các dòng và trong bước thứ hai xóa nó.


4

Tôi biết đây là vikênh, nhưng với tôi đây là một sedvấn đề.

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

Vì vậy, bạn có thể sắp xếp nó thành một vigiải pháp:

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

1
+1 cho giải pháp sed.
Christian Brabandt

3

Một cách khác (tôi cho rằng chúng ta bắt đầu trên dòng 1 và xóa các dòng 2-4, 6-8, v.v., theo một văn bản ví dụ):

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

Nếu thích làm điều này một cách tương tác, bạn có thể sử dụng "thanh ghi dòng lệnh". Đó là, nhấn

:+1del 3<CR> và sau đó 1000@:


1

một thay thế: bạn muốn giữ bất kỳ dòng nào: 1, 4, v.v. Bạn có thể sử dụng:

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

một cách khác: nếu bạn biết các dòng bạn muốn khớp với một số mẫu độc đáo:

# 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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.