Я хотел бы объединить строки только для линий, которые имеют определенный шаблон (например, ;
), однако при использовании g/;/j
он не работает, как ожидалось, если не вызывается пару раз.
Например следующее содержание:
a
1;
2;
3;
4;
5;
b
6;
7;
8;
9;
c
при использовании: :g/;/j
вывод:
a
1; 2;
3; 4;
5; b
6; 7;
8; 9;
c
или :g/;/-j
дает:
a 1; 2; 3; 4; 5;
b 6; 7; 8; 9;
c
аналогично с: :g/;\_.\{-};/j
.
Мой ожидаемый результат:
a
1; 2; 3; 4; 5;
b
6; 7; 8; 9;
c
или что-то подобное, поэтому все строки, содержащие шаблон, объединяются.
Как этого можно достичь?
global-command
kenorb
источник
источник
:g/;/j
не работает, потому что это делается в два прохода: сначала сканируется буфер, затем команда применяется к совпадающим строкам.Ответы:
Возможное объяснение проблемы
Я думаю, что причина
:g/;/j
не работает, потому что:g
команда работает с 2-х проходным алгоритмом:;
Во время второго прохода
:g
соединяет линию1;
со строкой,2;
потому что1;
был отмечен во время первого прохода. Однако я подозреваю (не уверен) , что он не вступает1; 2;
с ,3;
потому что линия2;
больше не существует, его содержание было объединено с линией ,1;
которая уже была обработана.Поэтому
:g
ищет следующую строку, которая была отмечена во время первого прохода (3;
), и объединяет ее со следующей (4;
). После того, что проблема повторяется, она не может присоединиться к3; 4;
с ,5;
потому что линия4;
больше не существует.Решение 1 (с vimscript)
Возможно, вы можете вызывать функцию всякий раз, когда
;
найдена строка, содержащая строку, чтобы проверить, содержит ли предыдущая строка точку с запятой:Затем используйте следующую глобальную команду:
Или без функции:
Решение 2 (без vimscript)
Всякий раз, когда глобальная команда
:g
находит шаблон,;
она выполняет команду:.,/^[^;]*$/-1j
Это может быть разбито так:
Куда :
b
может быть разбит дальше, как это:j
это сокращенная форма команды Ex,:join
которой, как и большинству других команд Ex, может предшествовать диапазон.Здесь ему предшествует диапазон:
.,/^[^;]*$/-1
(a,b
)Диапазон следует за формой,
a,b
гдеa
иb
обычно представляют собой 2 номера строки, и позволяет вам работать с группой строк, число которых находится междуa
иb
вместо одной.Таким образом,
j
команда объединяет все строки между текущей (a
) и следующей строкой, которая не содержит точку с запятой минус один (b
).Для получения дополнительной информации см .:
источник
Я делаю подобное соединение все время с глобальным поиском и заменой:
\n
соответствует новой строке.Чтобы найти и удалить пустые строки:
Я не уверен, почему, но если вы хотите вставить новую строку, вы должны использовать
\r
источник
s
один будет работать только для одной строки, чтобы сделать его глобальным, его нужно использовать%s
, но затем он объединит почти все строки, включая не;
строки:s
команду именно для того, что вы хотите. Я думаю, что это%s/;\n\(.*;\)\@=/;/
делает то, что вам нужно.