Можливе пояснення проблеми
Я думаю, що причина :g/;/jне працює в тому, що :gкоманда працює з двопрохідним алгоритмом:
- під час першого проходження він позначає лінії, що містять візерунок
;
- під час другого проходу він працює на позначених лініях
Під час другого проходу :gприєднується до рядка 1;з рядком, 2;оскільки він 1;був позначений під час першого проходу. Однак я підозрюю (не впевнений) , що він не вступає 1; 2;з , 3;тому що лінія 2;більше не існує, його зміст було об'єднано з лінією , 1;яка вже була оброблена.
Тому :gшукає наступний рядок, який був позначений під час першого пропуску ( 3;), і з'єднує його з наступним ( 4;). Після цього проблема повторюється, вона не може приєднатися 3; 4;до неї, 5;оскільки лінія 4;вже не існує.
Рішення 1 (з vimscript)
Можливо, ви можете викликати функцію кожного разу, коли ;буде знайдено рядок, що містить , щоб перевірити, чи містить попередній рядок крапку з комою:
function! JoinLines()
if getline(line('.')-1) =~ ';'
.-1join
endif
endfunction
Потім використовуйте таку глобальну команду:
:g/;/call JoinLines()
Або без функції:
:g/;/if getline(line('.')-1) =~ ';' | -j | endif
Рішення 2 (без вимскрипту)
:g/;/.,/^[^;]*$/-1j
Щоразу, коли глобальна команда :gзнаходить шаблон, ;вона виконує команду: .,/^[^;]*$/-1j
Його можна розбити так:
:g/pattern/a,bj
Де:
pattern = ;
a = . = number of current line
b = /^[^;]*$/-1 = number of next line without any semicolon minus one
b можна поділити далі так:
/ = 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є скороченою формою команди Ex, :joinякій, як і більшості інших команд Ex, може передувати діапазон.
Тут йому передує діапазон: .,/^[^;]*$/-1( a,b)
Діапазон слідує за формою, a,bде aі, bяк правило, 2 номери рядків, і дозволяє оперувати групою рядків, число яких між aі b, а не однією.
Таким чином jкоманда з'єднує всі рядки між поточним ( a) та наступним, який не містить крапки з комою мінус один ( b).
Для отримання додаткової інформації див:
:help :global
:help :join
:help :range
:g/;/jне працює, оскільки це робиться за два проходи: спочатку буфер сканується, потім команда застосовується до відповідних рядків.