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

21

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

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

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

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

200_success
источник

Ответы:

24

Это действительно гениально. Давайте разберемся с этим. exкоманда

g/^$/xyzzy

будет искать все пустые строки и выполнять xyzzyкоманду (произвольную exкоманду) на каждой из них. Обратите внимание, что 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,2 ничего не делает.

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

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

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

Это основано на том факте, что в vimдокументации указан двухпроходный алгоритм: один для разметки строк, другой для выполнения операции.


источник
2
Обратите внимание, что эта команда будет жаловаться, если у вас есть пустые строки в конце вашего файла.
Уайлдкарт