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

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

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

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

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

1 Ответ

49 голосов
/ 13 июня 2010

Это действительно довольно гениально.Давайте разберемся с этим.Команда 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 указан двухпроходный алгоритм: один для разметки строк, другой для выполнения операции.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...