Если, конечно, ваш файл содержит менее 20 000 строк :-)
paxdiablo
3
На самом деле ты ошибаешься, Майкл. Это работает безупречно, поскольку VI прекратит запуск макроса, как только достигнет конца файла. Вы можете легко попробовать это на примере выше.
rui
1
Ну, как и любой макрос, вам нужно сделать это правильно с первого раза, но после этого вы можете применить к любому файлу, просто набрав 10000 @ q. В любом случае, я считаю, что это всего лишь вопрос вкусов, поэтому я решительно не собираюсь начинать философские дебаты. :)
rui
3
Я предпочитаю использовать «макрос». Используя макрос, вы «описываете», как вы решите одну конкретную задачу, и позволяете VIM повторять ее за вас. RUI, я бы предпочел использовать j вместо клавиши со стрелкой.
Элегантный (и эффективный) способ выполнить задачу - вызвать :+deleteкоманду, удаляющую строку, следующую за текущей, в каждой строке с помощью :globalкоманды:
Почему этот ответ не получил больше голосов? Это так чисто и просто. В качестве альтернативы вы можете удалить первую строку и выполнить указанную выше команду, чтобы удалить все нечетные строки.
Usagi
3
@Usagi: Спасибо! Я так же отношусь к этому. И да, вы абсолютно правы, :1d|g/^/+dудаляет лишние строчки.
ib.
@Usagi Другой ответ был выбран как «лучший ответ» за 2 года до его появления. Кроме того, хотя это более элегантное решение, его можно было бы написать более полезным способом (т. Е. Нет упоминания о том, что делает ^, а макрос прост для понимания).
user1271772
3
Извините, но без объяснения того, как эта команда выполняет желаемое поведение, я бы не проголосовал за нее, а вместо этого предпочел бы принятый ответ, так как я понимаю, как он достигает цели. В этом разница между тем, чтобы дать мужчине рыбу и научить его ловить рыбу.
Гейб
3
Я не знаю, этот ответ заставил меня пойти и научиться ловить рыбу с помощью команды: g (то есть заставило меня погуглить эту страницу - vim.wikia.com/wiki/Power_of_g ).
Snetch
67
Мы можем использовать :normalили :normдля выполнения заданных команд нормального режима. Источник.
Этому ответу не уделяется достаточно внимания, возможно, из-за отсутствия объяснения здесь и в связанной, грязной шпаргалке. команда norm запускает команды нормального режима, эквивалентные буквам, которые следуют за ней. Итак, здесь выполняется j для перемещения вниз по строке и dd для ее удаления. Это можно обобщить до X-й строки, добавив в этом случае больше 'j'.
imoatama
5
а% - это сокращение для 1, $ (выполните следующую команду со строки 1 до конца)
Ламбарт,
3
Меня интересует, почему %norm ddjне работает, если вы хотите удалить нечетные строки.
Cyker
10
:map ^o ddj^o
^o
Здесь ^ обозначает CTRL. Рекурсивный макрос для удаления строки каждые две строки. Хорошо выберите первую строчку, и готово.
Тогда я бы предпочел !perl -ne 'print unless $. % 2':-)
Alex Brasetvik
И, Алекс, я определенно предпочитаю свое решение твоему, но это стоит рассмотреть, поскольку это единственное разумное решение, использующее здесь только сам vim.
Михаил Крелин - хакер
Макро-путь намного проще.
trusktr
+1 из-за гибкости, с if (expression)которой также работает для каждой третьей строки и т. Д.
Йенс
5
Вы всегда можете передать команду оболочки, что означает, что вы можете использовать любой язык сценариев, который вам нравится:
:%!perl -nle 'print if $. % 2'
(или используйте «если» вместо «если», в зависимости от того, какие строки вы хотите)
Вам не нужен -lпереход на Perl ... также, я бы сказал, что awkон немного более распространен, чем Perl, хотя на самом деле в наши дни он не намного больше и может сделать это короче: :%!awk NR\%2или :%!awk 1-NR\%2для других строк.
ephemient
4
:%!awk -- '++c\%2'
альтернативно
:%!awk -- 'c++\%2'
в зависимости от того, какую половину вы хотите отсеять.
Эмм, почему бы не использовать существующую NRпеременную?
ephemient
Правильно. Потому что я забыл об этом. ;-) Но на самом деле «правильный» вариант с NR будет еще длиннее. И не было бы двух симпатичных аналогов.
Михаил Крелин - хакер
:%!awk NR\%2или :%!awk 1-NR\%2, как я написал в другом комментарии. Это вряд ли дольше.
ephemient
1
1-NRдлиннее чем c++. Да, я знаю, что это один персонаж. Как я уже сказал, настоящая причина в том, что я забыл об этом. Во всяком случае, похоже, что люди не ценят здесь красоты awk.
Михаил Крелин - хакер
И NRкороче ++c:)
ephemient
3
Вы можете использовать собственные возможности Vim для поиска и замены, например: Поместите курсор в первую строку и введите в обычном режиме:
:.,/fff/s/\n.*\(\n.*\)/\1/g
Это .,/fff/диапазон для замены. Это означает «от этой строки до строки, соответствующей регулярному выражению fff(в данном случае последней строки).
s///это замещающая команда. Он ищет регулярное выражение и заменяет каждое его вхождение строкой. Знак gв конце означает повторение подстановки до тех пор, пока регулярное выражение будет найдено.
Регулярное выражение \n.*\(\n.*\)соответствует новой строке, затем целой строке ( .*соответствует любому количеству символов, кроме новой строки), затем еще одной новой строке и другой строке. Скобки \(и \)вызывают запись выражения внутри них, чтобы мы могли использовать его позже, используя \1.
\1 вставляет сгруппированную новую строку и строку после нее обратно, потому что мы не хотим, чтобы следующая строка тоже уходила - мы просто хотим, чтобы механизм подстановки прошел мимо нее, чтобы мы не удаляли ее при следующей замене.
Таким образом, вы можете контролировать диапазон, в котором вы хотите, чтобы произошло удаление, и вам не нужно использовать какие-либо внешние инструменты.
b = cb[:]временно копирует все строки в текущем буфере в b. b[::2]получает каждую вторую строку из буфера и назначает ее всему текущему буферу cb[:]. Копирование в bнеобходимо, поскольку буферные объекты, похоже, не поддерживают расширенный синтаксис среза.
Вероятно, это не «путь vim», но его будет легче запомнить, если вы знаете Python.
Чтобы удалить нечетные строки (1,3,5, ..) -> :%s/\(.*\)\n\(.*\)\n/\2\r/g
Чтобы удалить четные строки (2,4,6, ..) -> :%s/\(.*\)\n.*\n/\1\r/g
Найдите текст (формирует первую строку), за которым следует символ новой строки и еще немного текста (формирует вторую строку), за которым следует другой символ новой строки, и замените указанное выше либо первым совпадением (нечетная строка), либо вторым совпадением (четная строка) с последующим возвратом каретки.
:% !sed -e '2~2 d'
^^^^ pipe file through a shell command
^^^^^^ the command is sed, and -e describes an expression as parameter
^^^^^ starting with the second line, delete every second line
Ответы:
Для этого можно использовать макрос. Сделайте следующее.
gg
.qq
.dd
после.q
.10000@q
PS: Чтобы перейти в командный режим, просто нажмите Escape пару раз.
источник
:g/^/+d
от пользователя stackoverflow.com/users/254635/ib (ниже) - более элегантный способ решить эту проблему.Элегантный (и эффективный) способ выполнить задачу - вызвать
:+delete
команду, удаляющую строку, следующую за текущей, в каждой строке с помощью:global
команды:источник
:1d|g/^/+d
удаляет лишние строчки.Мы можем использовать
:normal
или:norm
для выполнения заданных команд нормального режима. Источник.источник
%norm ddj
не работает, если вы хотите удалить нечетные строки.Здесь ^ обозначает CTRL. Рекурсивный макрос для удаления строки каждые две строки. Хорошо выберите первую строчку, и готово.
источник
из почтового архива vim :
(При вводе в одной строке командной строки vim удаляются строки 1,3,5,7, ...)
источник
!perl -ne 'print unless $. % 2'
:-)if (expression)
которой также работает для каждой третьей строки и т. Д.Вы всегда можете передать команду оболочки, что означает, что вы можете использовать любой язык сценариев, который вам нравится:
(или используйте «если» вместо «если», в зависимости от того, какие строки вы хотите)
источник
-l
переход на Perl ... также, я бы сказал, чтоawk
он немного более распространен, чем Perl, хотя на самом деле в наши дни он не намного больше и может сделать это короче::%!awk NR\%2
или:%!awk 1-NR\%2
для других строк.альтернативно
в зависимости от того, какую половину вы хотите отсеять.
источник
NR
переменную?:%!awk NR\%2
или:%!awk 1-NR\%2
, как я написал в другом комментарии. Это вряд ли дольше.1-NR
длиннее чемc++
. Да, я знаю, что это один персонаж. Как я уже сказал, настоящая причина в том, что я забыл об этом. Во всяком случае, похоже, что люди не ценят здесь красоты awk.NR
короче++c
:)Вы можете использовать собственные возможности Vim для поиска и замены, например: Поместите курсор в первую строку и введите в обычном режиме:
.,/fff/
диапазон для замены. Это означает «от этой строки до строки, соответствующей регулярному выражениюfff
(в данном случае последней строки).s///
это замещающая команда. Он ищет регулярное выражение и заменяет каждое его вхождение строкой. Знакg
в конце означает повторение подстановки до тех пор, пока регулярное выражение будет найдено.\n.*\(\n.*\)
соответствует новой строке, затем целой строке (.*
соответствует любому количеству символов, кроме новой строки), затем еще одной новой строке и другой строке. Скобки\(
и\)
вызывают запись выражения внутри них, чтобы мы могли использовать его позже, используя\1
.\1
вставляет сгруппированную новую строку и строку после нее обратно, потому что мы не хотим, чтобы следующая строка тоже уходила - мы просто хотим, чтобы механизм подстановки прошел мимо нее, чтобы мы не удаляли ее при следующей замене.Таким образом, вы можете контролировать диапазон, в котором вы хотите, чтобы произошло удаление, и вам не нужно использовать какие-либо внешние инструменты.
источник
$
вместо/fff/
, для конца файла, независимо от содержимого файла.В качестве другого подхода вы также можете использовать python, если ваш vim поддерживает его.
b = cb[:]
временно копирует все строки в текущем буфере вb
.b[::2]
получает каждую вторую строку из буфера и назначает ее всему текущему буферуcb[:]
. Копирование вb
необходимо, поскольку буферные объекты, похоже, не поддерживают расширенный синтаксис среза.Вероятно, это не «путь vim», но его будет легче запомнить, если вы знаете Python.
источник
Чтобы удалить нечетные строки (1,3,5, ..) ->
:%s/\(.*\)\n\(.*\)\n/\2\r/g
Чтобы удалить четные строки (2,4,6, ..) ->
:%s/\(.*\)\n.*\n/\1\r/g
Найдите текст (формирует первую строку), за которым следует символ новой строки и еще немного текста (формирует вторую строку), за которым следует другой символ новой строки, и замените указанное выше либо первым совпадением (нечетная строка), либо вторым совпадением (четная строка) с последующим возвратом каретки.
источник
Вызвать sed:
источник
решение
вы можете попробовать это в vim
редактировать
Постараюсь пояснить (две части)
первая часть диапазон выбора (
:from,to
)вторая часть действие (
d
удалить):1,$-1
)g
) delete (+1d
) следующая строкавы можете попробовать перейти к первой строке вашего файла и выполнить,
:+1d
вы увидите, что следующая строка исчезнетЯ знаю, что это грязно, но это энергично и работает
источник