Я думаю, что следующая команда должна работать:
:%s/^\(.*\)\(\n\1\)\+$/\1/
Пояснение:
Мы используем команду замещения для всего файла, чтобы изменить pattern
на string
:
:%s/pattern/string/
Вот pattern
это ^\(.*\)\(\n\1\)\+$
и string
есть \1
.
pattern
может быть разбито так:
^\(subpattern1\)\(subpattern2\)\+$
^
и $
сопоставьте соответственно начало строки и конец строки.
\(
и \)
используются для включения, subpattern1
чтобы мы могли ссылаться на него позже по специальному номеру \1
.
Они также используются для включения, subpattern2
чтобы мы могли повторить это 1 или более раз с квантификатором \+
.
subpattern1
is .*
.
- это метасимвол, соответствующий любому символу, кроме новой строки, и *
квантификатор, соответствующий последнему символу 0, 1 или более раз.
Таким образом, .*
соответствует любой текст, не содержащий новой строки.
subpattern2
is \n\1
\n
соответствует новой строке и \1
соответствует тому же тексту, который был найден внутри первой \(
, \)
что здесь subpattern1
.
Таким образом, pattern
можно прочитать так:
начало строки ( ^
), за которым следует любой текст, не содержащий новой строки ( .*
), за которым следует новая строка ( \n
), затем тот же текст ( \1
), причем последние два повторяются один или несколько раз ( \+
), и наконец конец строки ( $
) .
Везде, где pattern
сопоставляется (блок идентичных строк), команда подстановки заменяет его тем, string
что здесь \1
(первая строка блока).
Если вы хотите увидеть, какие блоки строк будут затронуты, ничего не изменяя в вашем файле, вы можете включить эту hlsearch
опцию и добавить n
флаг замещения в конце команды:
:%s/^\(.*\)\(\n\1\)\+$/\1/n
Для более детального контроля вы также можете запросить подтверждение перед изменением каждого блока строк, добавив c
вместо этого флаг подстановки:
:%s/^\(.*\)\(\n\1\)\+$/\1/c
Для получения дополнительной информации о команде чтении подстановки :help :s
,
для замещения флагов :help s_flags
,
для различных метасимволов и кванторы чтения :help pattern-atoms
, так
и для регулярных выражения в Vim прочитать это .
Изменить: Подстановочный знак исправил проблему в команде, добавив $
в конце pattern
.
Также у BloodGain есть более короткая и читаемая версия этой же команды.
$
в этом, хотя. В противном случае он будет выполнять неожиданные действия со строкой, которая начинается с идентичного текста предыдущей строки, но содержит некоторые другие завершающие символы. Также обратите внимание, что основная команда, которую вы дали, функционально эквивалентна моему ответу:%!uniq
, но флаги выделения и подтверждения хороши.\n
соответствует концу строки и должен это предотвратить, но это не так. Я попытался добавить$
сразу после.*
безуспешно. Я собираюсь попытаться исправить это, но если я не могу, возможно, я удалю свой ответ или добавлю предупреждение в конце. Спасибо за указание на эту проблему.:%s/^\(.*\)\(\n\1\)\+$/\1/
$
соответствует концу строки , а не концу строки. Технически это неверно, но когда вы ставите символы после него, кроме нескольких исключений, он соответствует литералу,$
а не чему-то особенному. Таким образом, использование\n
лучше для многострочных матчей. (Смотрите:help /$
)\n
можете использовать в любом месте внутри регулярного выражения, тогда как,$
вероятно, следует использовать только в конце. Просто чтобы сделать разницу между ними, я отредактировал ответ, написав, что\n
соответствует новой строке (что инстинктивно заставляет вас думать, что после текста еще есть текст), тогда как$
соответствует концу строки (что заставляет вас думать, что ничего нет осталось).Попробуйте следующее:
Как и в случае ответа Сагино , здесь используется команда Vim: substitute. Однако для улучшения читабельности используются несколько дополнительных функций:
\v
означает «очень волшебный», или все символы, кроме буквенно-цифровых ( A-z0-9 ) и подчеркивания ( _ ), имеют особое значение.Значение компонентов:
источник
\n
и$
.\n
добавляет что-то к шаблону: символьная новая строка, которая сообщает vim, что следующий текст находится на новой строке. Принимая во внимание, что$
ничего не добавляет к шаблону, оно просто запрещает сопоставление, если следующий символ вне шаблона не является новой строкой. По крайней мере, это то, что я понял, прочитав ваш ответ и:help zero-width
.^
это ничего не добавляет к шаблону, оно просто предотвращает сопоставление, если предыдущий символ вне шаблона не является новой строкой ...+
означает «повторить предыдущее выражение (символ или группу) 1 или более раз», но ничего не соответствует самому себе. В^
означает «не может начаться в середине строки» и$
означает «не может заканчиваться в середине строки.» Заметьте, я не сказал "линия", но "строка" там. Vim обрабатывает каждую строку как строку по умолчанию - и вот тут-то и\n
приходит. Он говорит Vim использовать новую строку, чтобы попытаться найти совпадение.Если вы хотите удалить ВСЕ смежные идентичные строки, а не только
Hold
, вы можете сделать это очень легко с помощью внешнего фильтра изнутриvim
::%!uniq
(в среде Unix).Если вы хотите сделать это напрямую
vim
, это на самом деле очень сложно. Я думаю, что есть способ, но для общего случая очень сложно сделать его на 100% функциональным, и я еще не исправил все ошибки.Однако для этого конкретного случая, поскольку вы можете визуально увидеть, что следующая строка, которая не является дубликатом, не начинается с того же символа, вы можете использовать:
+
Означает строку после текущей строки. . относится к текущей строке./^[^H]/-
Означает линию до (-
) в следующей строке , которая начинается не с H.Затем я удалю.
источник
uniq
(изнутри vim или использование оболочки) - вот как я могу решить эту проблему. Во-первых, я уверен,uniq
что строки, которые будут пустыми / все пробелы будут эквивалентны (не проверял), будут обрабатываться с помощью регулярных выражений. Это также означает не «изобретать велосипед», пока я пытаюсь выполнить работу.Ответ на основе Vim:
= Замените каждую строку, за которой следует сама по крайней мере один раз , той же самой строкой.
источник
Еще один, предполагая Vim 7.4.218 или позже:
Это не обязательно лучше, чем другие решения, хотя.
источник
Вот решение, основанное на старом (2003) vim (golf) Пребена Гулберга и Пита Дельпорта.
%g/^\v(.*)\n\1$/d
:Uniq
(эквивалентно:%Uniq
),:1,Uniq
(от начала буфера до текущей строки),:Uniq<cr>
(расширенный vim в:'<,'>Uniq
):h range
)Вот код:
Примечание: их первые попытки были:
источник