Có thể giải thích vấn đề
Tôi nghĩ lý do tại sao :g/;/j
không hoạt động là vì :g
lệnh hoạt động với thuật toán 2-pass:
- trong lần đầu tiên, nó đánh dấu các dòng chứa mẫu
;
- trong lần chuyển thứ hai, nó hoạt động trên các đường được đánh dấu
Trong lần vượt qua thứ hai, :g
nối dòng 1;
với dòng 2;
vì 1;
được đánh dấu trong lần đầu tiên. Tuy nhiên tôi nghi ngờ (không chắc chắn) mà nó không tham gia 1; 2;
với 3;
vì dòng 2;
không tồn tại nữa, nội dung của nó đã được sáp nhập với dòng 1;
mà đã được xử lý.
Vì vậy, :g
tìm kiếm dòng tiếp theo được đánh dấu trong lần đầu tiên vượt qua ( 3;
) và nối nó với dòng sau ( 4;
). Sau đó lặp đi lặp lại vấn đề, nó không thể tham gia 3; 4;
với 5;
vì dòng 4;
không tồn tại nữa.
Giải pháp 1 (có vimscript)
Có lẽ bạn có thể gọi một hàm bất cứ khi nào ;
tìm thấy một dòng chứa để kiểm tra xem dòng trước đó có chứa dấu chấm phẩy hay không:
function! JoinLines()
if getline(line('.')-1) =~ ';'
.-1join
endif
endfunction
Sau đó sử dụng lệnh toàn cầu sau:
:g/;/call JoinLines()
Hoặc không có chức năng:
:g/;/if getline(line('.')-1) =~ ';' | -j | endif
Giải pháp 2 (không có vimscript)
:g/;/.,/^[^;]*$/-1j
Bất cứ khi nào lệnh toàn cầu :g
tìm thấy mẫu, ;
nó sẽ thực thi lệnh: .,/^[^;]*$/-1j
Nó có thể được chia nhỏ như thế này:
:g/pattern/a,bj
Ở đâu :
pattern = ;
a = . = number of current line
b = /^[^;]*$/-1 = number of next line without any semicolon minus one
b
có thể được chia nhỏ hơn nữa như thế này:
/ = look for the number of the next line matching the following pattern
^ = a beginning of line
[^;] = then any character except a semicolon
* = the last character can be repeated 0 or more times
$ = an end of line
/ = end of pattern
-1 = removes one to the number you just got
j
là dạng viết tắt của lệnh Ex :join
, giống như hầu hết các lệnh Ex khác có thể được bắt đầu bằng một phạm vi.
Ở đây, nó đi trước phạm vi: .,/^[^;]*$/-1
( a,b
)
Một phạm vi theo mẫu a,b
trong đó a
và b
nói chung là 2 số dòng và cho phép bạn hoạt động trên một nhóm các dòng có số nằm giữa a
và b
, thay vì chỉ một.
Vì vậy, j
lệnh kết hợp tất cả các dòng giữa dòng hiện tại ( a
) và dòng tiếp theo không chứa bất kỳ dấu chấm phẩy trừ một ( b
).
Để biết thêm thông tin, xem:
:help :global
:help :join
:help :range
:g/;/j
không hoạt động vì nó được thực hiện trong hai lần: đầu tiên bộ đệm được quét, sau đó lệnh được áp dụng cho các dòng khớp.