Подтвердить что ты не робот

Как: g/^$/,/./- j (сокращение нескольких пустых строк до одного пробела) работает в vim?

В статье Vim Regular Exions Олег Райский дает следующую команду, чтобы уменьшить несколько пустых строк до одного пробела:

:g/^$/,/./-j

Может кто-нибудь описать, как это работает?

Я знаю команду :g и регулярные выражения. Но я не понял, что делает эта часть /,/./-j.

4b9b3361

Ответ 1

Это действительно изобретательно. Пусть сломается. Команда ex

g/^$/xyzzy

будет искать все пустые строки и выполнить команду xyzzy (произвольная команда ex) для каждого из них.

Трудный бит здесь заключается в том, что команда xyzzy в вашем случае представляет собой еще одну заменяющую команду:

,/./-j

,/./- указывает диапазон. Это имеет вид <start>,<end> и, поскольку перед запятой ничего нет, предполагается, что текущая строка (ту, где вы нашли пустую строку) - это начало.

После запятой /./-, что означает поиск следующего символа (. означает любой символ), затем резервное копирование одной строки (/./- является коротким для /./-1, поскольку это подразумевается, если не задано значение). Вы найдете этот шаблон . на первой непустой строке, следующей за той, над которой вы работаете.

Другими словами, конец диапазона - это последняя пустая строка после или в той, на которой вы сейчас работаете.

Затем вы выполняете объединение в этом диапазоне.

Если начало и конец диапазона были равны (в секции была только одна пустая строка), соединение ничего не делает. Если они не равны, присоедините их все.

То, как он объединяет несколько пустых строк в один.

Давайте посмотрим на пример (номера строк не находятся в файле):

1 Line 1
2
3 Line 3
4 Line 4
5
6
7
8
9 Line 9

Команда :g найдет все пустые строки и выполнит их работу над ними (строки 2, 5, 6, 7 и 8).

Для строки 2 ,/./-j будет задан диапазон от 2 до 2 (следующий ., найденный в строке 3, а затем вычтите 1). Соединение в диапазоне 2,2 ничего не делает.

В строке 5 ,/./-j будет задан диапазон от 5 до 8 (следующий ., найденный в строке 9, затем вычтите 1). Соединение в диапазоне 5,8 соединяется со всеми этими линиями вместе.

Я не совсем уверен в этом, но я думаю, что операция не может выполняться в строках, которые исчезают как часть более ранней операции. Это потому, что было бы бессмысленно обрабатывать строки, которые были удалены ранее в цикле.

Другими словами, поскольку строки с 6 по 8 удаляются (в сочетании с строкой 5), глобальная команда не работает после них. Я основываю это не что иное, как тот факт, что документация vim содержит двухпроходный алгоритм, один для отметки строк, один для выполнения операции.

Возможно, я ошибаюсь в этой точке (это будет не первый раз), но это деталь реализации, которая не влияет на функциональность.