Câu trả lời:
Lệnh gim của Vim được thiết kế cho chính xác loại nhiệm vụ này; chạy một hành động duy nhất trên mỗi dòng phù hợp với một mẫu cụ thể. Đây là câu trả lời của tôi:
:g/.\n\n\@!/norm o
Mẫu tôi sử dụng là /.\n\n\@!/
. Chia nó thành các phần thành phần của nó:
.
Phù hợp với bất kỳ nhân vật trong dòng. (được sử dụng để loại bỏ ngay lập tức mọi dòng trống hiện có khỏi xem xét)\n
Khớp một \ n ở cuối ký tự ở trên\n\@!
Thất bại trận đấu nếu có một \ n khác ngay sau \ n trước đó.(Kiểm tra :h E59
để biết thêm thông tin về\@!
và các công cụ xác định đối sánh tương tự trong các biểu thức thông thường - cũng có một vài cái khác!)
Vì vậy, regex của lệnh g hiện đã chọn mọi dòng không trống được kết thúc bởi một dòng mới và không theo sau bởi một dòng trống.
Sau khi mẫu trong một :g
câu lệnh xuất hiện lệnh để chạy trên các dòng khớp. Trong trường hợp này, tôi đã bảo nó thực thi lệnh chế độ bình thường (viết tắt là norm
) và lệnh để chạy đơn giản o
, nó chèn một dòng trống bên dưới dòng hiện tại.
Vì vậy, được thực hiện cùng nhau, lệnh tìm thấy mọi dòng không có một dòng trống bên dưới nó và thêm một dòng. Và đó là tất cả để có nó! Bạn có thể muốn kiểm tra bài viết Power of G của vim wiki để biết những điều thú vị hơn bạn có thể làm với :g
(và đó là chị em tiêu cực :v
) - đó là một trong những lệnh hữu ích đáng kinh ngạc mà bạn sớm phát triển để dựa vào, và sau đó bỏ lỡ rất nhiều trong các biên tập viên Mà không có nó.
:%s/$/
, rồi đánh ^V
, rồi đánh Enter
.
:%s/$/<C-V><CR><CR>
(để sử dụng mã hóa vim-dân gian phổ biến của các phím bấm), cách tiếp cận đó chỉ thêm một dòng mới sau mỗi dòng. Đó là, các dòng đã được phân tách bằng khoảng trắng (xem Dòng 3 -> Dòng 4, trong văn bản ví dụ) kết thúc để có thêm các dòng trống. Câu hỏi ban đầu là để tránh thêm các dòng trống bổ sung nơi chúng đã tồn tại trong văn bản bắt đầu.
Khi tôi kiểm tra câu trả lời tìm kiếm và thay thế toàn cầu của @ NeilForester, tôi thấy rằng nó đã bỏ lỡ mỗi giây thay thế dự định trong các dòng không trống liên tiếp nếu mỗi dòng chỉ có một ký tự. Điều này dường như là do mô hình bắt đầu khớp với mỗi lần sau ký tự cuối cùng mà nó khớp với lần trước.
Sử dụng lookbehind và lookahead sẽ giải quyết vấn đề này và làm cho regex ngắn hơn một chút:
:%s/\n\@<!\n\n\@!/\r\r/g
\n\@<!\n
có nghĩa là bất kỳ ngắt dòng nào không đúng sau khi ngắt dòng khác là đúng? Nhưng tôi không thể hiểu ý \n\@!
nghĩa của nó. Tôi muốn hiểu nó để tôi có thể tìm hiểu và áp dụng nó cho các mẫu tìm kiếm khác :)
\n\@<!\n
có nghĩa là bất kỳ ngắt dòng nào không ngay lập tức theo sau một ngắt dòng khác. \n\@!
khớp với độ rộng bằng không nếu nguyên tử trước (tức là \n
) không khớp ngay trước những gì tiếp theo. Hãy thử :help \@<!
xem tài liệu về điều này trong vim. Tôi
Đúng nếu tôi đã sai lầm. Tôi tin rằng bạn sử dụng chữ k khi ở chế độ lệnh để di chuyển xuống một dòng. Sau đó vào chế độ chèn và thêm dòng tiếp theo. Lặp lại khi cần thiết? Hi vọng điêu nay co ich!
k
di chuyển lên một dòng. j
di chuyển xuống một dòng.
/[^\n]\n[^\n]
:map <F2> no<esc><F2>
Sau đó nhấn <F2>
. Điều đó sẽ tìm kiếm hai dòng không trống liên tiếp, và sau đó thêm một dòng giữa chúng, lặp đi lặp lại.
Biên tập:
Đây là một cách khác để làm điều đó với một tìm kiếm và thay thế toàn cầu duy nhất:
:%s/\([^\n]\)\n\([^\n]\)/\1\r\r\2/g
Hãy thử lệnh này ( 16
ký tự):
:%!sed G|cat -s
:%norm o
nhưng hóa ra điều này không hoạt động như dự định trong trường hợpo
. +1