Можливе пояснення проблеми
Я думаю, що причина :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
не працює, оскільки це робиться за два проходи: спочатку буфер сканується, потім команда застосовується до відповідних рядків.