Видалити n рядків пропустити сценарій 1 рядка


10

Я хочу створити базовий скрипт Vim, який просто видаляє n рядків, пропускає 1 рядок і повторюється до кінця документа. Мене не цікавлять конкретні матчі, я просто хочу видалити рядок. Наприклад; Тому я хочу повторити команду 3ddjдля всього документа.

Text I want to keep.   
Text I want to delete.  
Text I want to delete.  
Text I want to delete.  
Text I want to keep.  
Text I want to delete.  
Text I want to delete.  
Text I want to delete.  
Text I want to keep.  
Text I want to delete.  
Text I want to delete.  
Text I want to delete.   

Так виглядає ...

Text I want to keep.  
Text I want to keep.  
Text I want to keep.  

Дякую.


Ви включили тег regular-expressionу своє запитання, але, схоже, питання не вказує на причину цього робити за допомогою регулярних виразів. Якщо ви насправді шукаєте те, що використовує регулярні вирази, stackoverflow.com/questions/17735289/… може зацікавити. Це запитання стосувалося Notepad ++, але у відповіді не використовується нічого, крім рекреації pcre. (Відмова: Я написав цю відповідь.)
Джаспер,

Наступного разу, коли ви ставите запитання, не потрібно писати "Дякую за це. Чудове рішення!" на кожну відповідь. Це навіть виписується, коли ви намагаєтесь створити новий коментар до відповіді.
труба

Щоб додати до цього, правильним способом проявити вдячність тут є прийняття відповіді, яка найкраще працювала для вас, та висловлення будь-яких відповідей, які ви вважаєте корисними чи корисними. Люди швидше побачать це, ніж коментар "спасибі".
B Layer

Відповіді:


19

Дуже простий підхід:

  1. Перейдіть до першого рядка, який потрібно видалити.
  2. Запис макросу: qa3ddjq
  3. Повторіть це з великою кількістю: 1000 @ a

Крок третій повторить макрос тисячу разів або поки не буде виявлена ​​помилка. Натискання на кінець файлу (отже, немає рядків для видалення) створює помилку, а повторення макросу скасовується.

Див :help recording.


2
Це дивовижно!!! Дякую велике, що працювало на мене: D
Макс Коплі

1
пояснення: q(у командному режимі та у vim чи інших останніх альтернативних версіях [neovim тощо), але не в оригіналі vi) означає "почати запис та помістити його в буфер" наступної літери ". отже: qaозначає "почати запис у буфер" а ". Потім qзаписуються всі клавіші, введені після цього (до наступного в командному режимі) (можна навіть записати: перехід у режим редагування, щось введення, вхід у командний режим тощо). Потім 12@aповторив би всі дії, записані в буфер "a" 12 разів.
Олів'є

3
Крім того, якщо ви не хочете запускати щось на кшталт 1000@qв кінці, ви можете зробити рекурсивний макрос:, qa3ddj@aq@aхоча вам, можливо, доведеться це зробити qaqспочатку, щоб переконатися, що "aзапускається порожнім.
Джеймс

17

Найпростішим рішенням для мене було б:

:%norm j3dd

Це є:

  • %: для кожного рядка
  • norm: запускайте такі клавіші, як ніби в звичайному режимі
  • j3dd: перейти вниз, а потім видалити 3 рядки

Тож з першого рядка переходьте до другого та видаляйте наступні 3 рядки. Другий Text I want to keep.зараз на другому рядку. Спустіться вниз по одному рядку, видаліть 3. Промийте і повторіть.


Примітка: якщо ви не хочете обробляти весь файл, його можна замінити, %normнаприклад, 5,$normобробити з 5-го рядка до кінця файлу.


4
Дуже приємна альтернатива! Працює in vim (не vi). Я ніколи раніше не чув про "норму"! (і я є своєрідним ви [м] вунком)
Олів'є

6

У вас вже є чудові рішення. Ось ще одна:

:g/^/if line('.')%4!=1|:s/^/DELETE ME/|endif
:g/^DELETE ME/d

По-перше, ми виконуємо дію на кожному рядку ( :gспівставляючи проти ^(початок рядка)) і за кожним номером рядка виконуємо результат linenumber % 4. Якщо результат нерівний 1, додаємо DELETE MEна початку рядка, позначаючи рядки, які слід видалити наступною командою.

Наступна команда - це звичайна ( :g) команда, яка відповідає всім рядкам, що починаються з цього DELETE MEта робить це.

Зауважте, ви не можете відразу видалити рядок за допомогою першої :gкоманди, оскільки це змінило б отриманий модуль обчислення, і як такий, ми повинні спочатку позначити рядки, а на другому кроці - видалити його.


4

Я знаю, що це viканал, але для мене це sedпроблема.

sed -ne 'p;n;n;n' <file >newfile

Таким чином, ви можете вкласти це в viрішення:

:0
!Gsed -ne 'p;n;n;n'

1
+1 для розчину sed.
Крістіан Брабандт

3

Альтернатива (я думаю, ми починаємо з рядка 1 і видаляємо рядки 2-4, 6-8 і так далі, як у прикладі тексту):

while line(".") < line("$")
    silent +1delete _ 3
endwhile

Якщо ви віддаєте перевагу робити це інтерактивно, ви можете скористатися "регістром командного рядка". Тобто натисніть

:+1del 3<CR> і потім 1000@:


1

альтернатива: ви хочете зберегти будь-які рядки: 1, 4 тощо. Ви можете використовувати:

awk '!((FNR-1)%3)'  file > newfile
      # awk: when a condition is given without action:
      #        prints the lines for which the condition returns 0.
      # FNR designates the line number in the current file.
      # a%3 : takes the modulus of a and 3. ( 0%3=0, 1%3=1, 2%3=2, 3%3=0, 4%3=1, etc.) 
      # This will be 0 for 3, 6, etc. 
      # But we want it to be 0 (true) for 1, 4, etc : so we substract 1 to NR

# to see that it keeps those lines:
seq 1 20 | awk '!((NR-1)%3)'
1
4
7
10
13
16
19

інша альтернатива: якщо ви знаєте, що потрібні лінії відповідають одному унікальному шаблону:

# for exemple each line you want contains "some pattern":
fgrep "some pattern" file > newfile
# (or regular grep if you want "some pattern" to be interpreted as a regexp)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.