Видалити 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.