Привет, коллеги! Часто бывает надо соединить две (или более) строк в одну. Давайте посмотрим повнимательнее.
Строка текста заканчивается символом конца строки, в Линукс это символ 0x0A, в Windows пара символов 0x0D 0x0A (возврат каретки и новая строка, наследие пишущих машинок). В Юникоде есть ещё несколько символов.
В регулярных выражениях символ конца строки обозначается \n и вот мы уже можем соединить строки:
:s/\n/ /
Кроме того, к любому классу символов можно добавить нижнее подчеркивание _ (кто нибудь видел верхнее подчеркивание?!) и тогда класс содержит ещё и конец строки. Вот несколько примеров:
\_. (любой символ, в том числе и конец строки), \_d (цифра или конец строки), \_[a-z] (буква латинского алфавита или конец строки), \_s (пробельный символ или конец строки), \_S (непробельный символ или конец строки).
С их помощью можно делать замены (или поиск) невзирая на границы строк. При замене строки сольются, так как символ конца строки будет заменен. Пример:
:%s/\_s\{2,}/ /g
Эта команда заменит два и более пробельных символов (включая и конец строки) на один пробел.
Есть и специальные команды для удаления символа конца строки, то есть для соединения строк в одну. Они бывают полезны, так как иногда удобно иметь форматированный текст, в котором концы строк расставлены исходя из представления текста на экране (или на печати), а иногда лучше иметь длинные строки, где конец строки по сути есть конец абзаца.
Средства для форматирования мы уже обсуждали. Теперь решим обратную задачу: соединить строки.
Основная команда нормального режима J. Она удаляет символ конца строки, присоединяя к текущей строке следующую. Однако ещё она удаляет отступ предыдущей строки и может вставить пробел или даже два. Один пробел заменит удаленный символ конца строки, но он не ставится, если на конце строки есть уже пробелы или если следующая строка начинается с закрывающей круглой скобки ). Второй пробел ставится, если строка кончилась точкой, восклицательным или вопросительным знаком. Это можно отключить, сбросив флаг joinspaces. Если опция cpoptions содержит флаг j, то второй пробел добавляется только после точки.
В конце первой строки ставится метка '[, в конце полученной строки - метка `].
Команда может применяться с повторителем или на выделении, склеивая сразу много строк. Только помните, что 2J это то же, что и просто J.
Если вам не надо удалять или добавлять пробелы, то есть вариант gJ. Он просто склеивает строки, не меняя их по существу.
Есть вариант для командной строки: :join. С восклицательным знаком работает как gJ, не трогая пробелы. Может работать на диапазоне или с указанием числа строк:
:1,+5join или :join 5
Вот как можно одной командой превратить параграфы (разделенные пустыми строками) в одиночные строки:
:g/\S/,/^\s*$/join
Это пример из Справки. Давайте разберём его. Итак, команда join дана на диапазоне, который имеет вид g/\S/,/^\s*$/
Через запятую указаны начальная и конечная строки: g/\S/ и /^\s*$/. Первая команда - глобальный фильтр строк, отсеивающий те, что содержат хоть один непробельный символ (\S). Это будет первая строка параграфа. Последняя строка диапазона ищется поиском / и должна состоять из одних пробелов: начало строки ^, пробелы \s* и конец строки.
Таким образом, join будет отрабатывать на параграфах, а g переберет их все, один за одним.
Давайте напоследок внесем ясность в разнообразие символов регулярных выражений, касающихся конца строки.
Есть \n, это именно символ конца строки. Если вы замените \n, то строка склеится со следующей.
Есть $, это якорь. Совпадение нулевой ширины, которое имеет место перед символом конца строки. в середине выражения совпадает с символом доллара. Так сделано потому, что при поиске в пределах строки искать конец строки в ее середине не слишком разумно. Если заменить $, то строка не склеится со следующей, потому что символ конца строки останется на своем месте.
Есть ещё \_$, который совпадает всегда перед концом строки и тоже является якорем. Может использоваться где угодно. Теперь это имеет смысл, так как есть возможности выйти за пределы строки:
text\_$\_s*
Это выражение означает "текст text, потом конец строки, потом пробелы (уже на новой строке, то есть отступ)".
Есть ещё \%$, который совпадает в конце всего файла. В Справке указано, что /VIM\_.\{-}\%$ не найдет последнее вхождение слова VIM в тексте, а найдет следующее. Логичность этого поведения не сразу становится ясна. Но становится. Ведь символ "что угодно" \_. должен совпасть как можно меньше (\{-}) раз до конца файла от найденного слова: это имеет место. Весь остаток файла, вместе с другими вхождениями слова, совпадает, причем минимальное число раз: укоротить-то якорь \%$ не дает! Решение задачи "найти последнее вхождение" с использованием ретроспективной проверки Справка дает, но проще искать с конца наверх: G?VIM
И последнее. После объединения строк они могут получиться длинные. Можно дать им уйти за край экрана (nowrap) или укладывать несколько логических строк на экран (wrap). Для перемещения по логическим строкам у нас есть gj, gk. Или можно использовать g со стрелками ↓ и ↑.
Если же вы выбрали nowrap, то есть команды g0, g^, gm и g$, переходящие на первый видимый символ строки (край окна), первый непробельный видимый символ, середину строки (середину окна), последний видимый символ. А для перемещения по строке есть W, E, B (прыжки по словам), f и t (поиск символа вправо, F и T влево, ; и , повторяют поиск и так можно, например, прыгать по предложениям от точки к точке), команда | переходит на символ по номеру.
Удачи, коллеги!