Usuń n linii, pomiń skrypt 1-liniowy


10

Chcę stworzyć podstawowy skrypt Vima, który po prostu usuwa n wierszy, pomija 1 wiersz i powtarza do końca dokumentu. Nie dbam o konkretne dopasowania, chcę po prostu usunąć linię. Na przykład; Chcę więc powtórzyć polecenie 3ddjdla całego dokumentu.

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.   

Wygląda to na ...

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

Dziękuję Ci.


Umieściłeś tag regular-expressionw swoim pytaniu, ale wydaje się, że pytanie nie określa powodu, dla którego należy to zrobić za pomocą wyrażeń regularnych. Jeśli faktycznie szukasz czegoś, co korzysta z wyrażeń regularnych, to stackoverflow.com/questions/17735289/... może być interesujące. To pytanie dotyczyło Notepad ++, ale w odpowiedzi użyto tylko wyrażenia regularnego pcre. (Zastrzeżenie: Napisałem tę odpowiedź.)
— Jasper,

Następnym razem, gdy zadasz pytanie, nie musisz pisać „Dzięki za to. Świetne rozwiązanie!” na każdą odpowiedź. Jest to nawet zapisane, gdy próbujesz utworzyć nowy komentarz do odpowiedzi.
— rura

Aby dodać do tego, właściwym sposobem okazania uznania jest zaakceptowanie odpowiedzi, która była dla Ciebie najlepsza i głosowanie za odpowiedziami, które uważasz za pomocne lub przydatne. Ludzie woleliby to zobaczyć niż komentarz „dzięki”.
— B Layer

Odpowiedzi:


19

Bardzo proste podejście:

  1. Przejdź do pierwszego wiersza, który chcesz usunąć.
  2. Nagraj makro: qa3ddjq
  3. Powtórz to z wysoką liczbą: 1000 @ a

Krok trzeci powtórzy makro tysiąc razy lub do momentu wystąpienia błędu. Wciśnięcie końca pliku (stąd brak wierszy do usunięcia) powoduje błąd, a powtórzenie makra jest anulowane.

Zobaczyć :help recording.


2
To jest wspaniałe!!! Dziękuję bardzo, że mi to zadziałało: D
— Max Copley,

1
objaśnienia: q(w trybie komend, w vimie lub innych najnowszych wersjach alternatywnych [neovim itp.], ale nie w oryginalnym vi) oznacza „rozpocznij nagrywanie i umieść go w buforze„ następnej litery ”. stąd: qaoznacza „rozpocznij nagrywanie w buforze„ a ”. Następnie wszystkie klawisze wpisane po tym (do następnego qw trybie poleceń) są zapisywane (możesz nawet nagrywać: przejście do trybu edycji, wpisanie czegoś, przejście do trybu poleceń itp.). Następnie 12@apowtórzyłby wszystkie działania zapisane w buforze „a” 12 razy.
— Olivier Dulac

3
Dodatkowo, jeśli nie chcesz uruchamiać czegoś takiego jak 1000@qna końcu, możesz utworzyć makro rekurencyjne: qa3ddj@aq@achociaż może zajść potrzeba, qaqaby upewnić się, że "azaczyna się od pustego.
— James

17

Najłatwiejszym rozwiązaniem byłoby dla mnie:

:%norm j3dd

To jest:

  • %: dla każdej linii
  • norm: uruchom następujące klawisze, jak w trybie normalnym
  • j3dd: zejdź na dół, a następnie usuń 3 linie

Więc od pierwszego wiersza zejdź do drugiego i usuń kolejne 3 wiersze. Drugi Text I want to keep.jest teraz na drugiej linii. Przejdź w dół o jedną linię, usuń 3. Opłucz i powtórz.


Uwaga: jeśli nie chcesz przetwarzać całego pliku, możesz go zastąpić %normnp. 5,$normAby przetworzyć od 5. linii do końca pliku.


4
Bardzo fajna alternatywa! Działa w vimie (nie vi). Nigdy wcześniej nie słyszałem o „normie”! (i jestem trochę maniakiem vi [m])
— Olivier Dulac

6

Masz już kilka świetnych rozwiązań. Oto kolejny:

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

Najpierw wykonujemy akcję na każdej linii ( :gdopasowując do ^(początku linii)) i dla każdego numeru linii wykonujemy wynik linenumber % 4. Jeśli wynik jest nierówny 1, dodajemy DELETE MEna początku linii, zaznaczając linie do usunięcia za pomocą następnego polecenia.

Następne polecenie to polecenie regularne ( :g), które pasuje do wszystkich linii, które zaczynają się od niego, DELETE MEi robi to.

Uwaga: Nie można natychmiast usunąć linii za pomocą pierwszego :gpolecenia, ponieważ zmieniłoby to wynikowe obliczenia modulo i jako takie musimy najpierw zaznaczyć linie, a w drugim etapie usunąć je.


4

Wiem, że to jest vikanał, ale dla mnie to sedproblem.

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

Możesz więc wdrożyć go do virozwiązania:

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

1
+1 za rozwiązanie sed.
— Christian Brabandt,

3

Alternatywa (przypuszczam, że zaczynamy od linii 1 i usuwamy linie 2-4, 6-8 itd., Jak w przykładowym tekście):

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

Jeśli wolisz robić to interaktywnie, możesz skorzystać z „rejestru wiersza poleceń”. To znaczy naciśnij

:+1del 3<CR> i wtedy 1000@:


1

alternatywa: chcesz zachować dowolne wiersze: 1, 4 itd. Możesz użyć:

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

inna alternatywa: jeśli znasz linie, które chcesz dopasować do jakiegoś unikalnego wzoru:

# 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)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.