Elimina n righe per saltare 1 riga di script


10

Voglio creare uno script Vim di base che elimina semplicemente n righe, salta 1 riga e si ripete fino alla fine del documento. Non mi interessano le partite specifiche, voglio solo eliminare la riga. Per esempio; Quindi voglio ripetere il comando 3ddjper l'intero documento.

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.   

Quindi sembra ...

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

Grazie.


Hai incluso il tag regular-expressionnella tua domanda, ma la domanda non sembra specificare un motivo per farlo con espressioni regolari. Se stai effettivamente cercando qualcosa che usi espressioni regolari, stackoverflow.com/questions/17735289/… potrebbe essere interessante. Quella domanda riguardava Notepad ++, ma la risposta non usa altro che un regex pcre. (Dichiarazione di non responsabilità: ho scritto quella risposta.)
Jasper,

La prossima volta che fai una domanda, non c'è bisogno di scrivere "Grazie per questo. Ottima soluzione!" su ogni singola risposta. Questo viene persino scritto quando si tenta di creare un nuovo commento su una risposta.
pipe:

Per aggiungere a ciò, il modo corretto di mostrare apprezzamento qui è accettare la risposta che ha funzionato meglio per te e votare tutte le risposte che ritieni utili o utili. La gente preferirebbe di gran lunga vedere questo che un commento di ringraziamento.
B Layer

Risposte:


19

Approccio molto semplice:

  1. Passa alla prima riga che desideri eliminare.
  2. Registra una macro: qa3ddjq
  3. Ripeti con un numero elevato: 1000 @ a

Il passaggio tre ripeterà la macro mille volte o fino a quando non si verifica un errore. Colpire la fine del file (quindi nessuna riga da eliminare) produce un errore e la ripetizione della macro viene annullata.

Vedere :help recording.


2
È stupefacente!!! Grazie mille, ha funzionato per me: D
Max Copley il

1
spiegazioni: q(in modalità comando e in vim o altre versioni alternative recenti [neovim, ecc], ma non nella vi originale) significa "avvia la registrazione e inseriscilo nel buffer" lettera successiva "". quindi: qasignifica "avvia la registrazione nel buffer" a ". Quindi vengono registrati tutti i tasti digitati dopo questo (fino al successivo qin modalità comando) (puoi persino registrare: entrare in modalità modifica, digitare qualcosa, Scorrere in modalità comando, ecc.). Quindi 12@aripeterebbe qualsiasi azione registrata nel buffer "a" 12 volte.
Olivier Dulac,

3
Inoltre, se non si desidera eseguire qualcosa di simile 1000@qalla fine, è possibile creare una macro ricorsiva:, qa3ddj@aq@aanche se potrebbe essere necessario eseguire qaqprima per assicurarsi che "ainizi vuoto.
James,

17

La soluzione più semplice per me sarebbe:

:%norm j3dd

Questo è:

  • %: per ogni linea
  • norm: esegue i seguenti tasti come in modalità normale
  • j3dd: andare in linea quindi eliminare 3 linee

Quindi dalla prima riga, scendi alla seconda ed elimina le 3 righe successive. Il secondo Text I want to keep.è ora sulla seconda riga. Scendi di una riga, elimina 3. Risciacqua e ripeti.


Nota: se non si desidera elaborare l'intero file, è possibile sostituire %normcon es. 5,$normPer elaborare dalla 5a riga alla fine del file.


4
Alternativa molto bella! Funziona in vim (non vi). Non ho mai sentito parlare di "norma" prima! (e io sono una specie di geek)
Olivier Dulac il

6

Hai già delle ottime soluzioni disponibili. Eccone un altro:

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

Innanzitutto, eseguiamo un'azione su ogni riga ( :gconfrontando con il ^(inizio della riga)) e per ogni numero di riga eseguiamo il risultato di linenumber % 4. Se il risultato non è uguale a 1, aggiungiamo DELETE MEall'inizio della riga, contrassegnando le righe da eliminare con il comando successivo.

Il comando successivo è un comando regolare ( :g), che corrisponde a tutte le righe che iniziano DELETE MEe lo fa.

Nota, non puoi eliminare immediatamente la riga usando il primo :gcomando, poiché ciò cambierebbe il calcolo del modulo risultante e come tale, dobbiamo prima contrassegnare le linee e in un secondo passo eliminarlo.


4

So che questo è il vicanale, ma per me questo è un sedproblema.

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

Quindi puoi affrontarlo in una visoluzione:

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

1
+1 per una soluzione sed.
Christian Brabandt,

3

Un'alternativa (suppongo che iniziamo dalla riga 1 ed eliminiamo le righe 2-4, 6-8 e così via, come da testo di esempio):

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

Se preferisci farlo in modo interattivo, puoi utilizzare il "registro della riga di comando". Cioè, premere

:+1del 3<CR> e poi 1000@:


1

un'alternativa: vuoi mantenere qualsiasi riga: 1, 4, ecc. Puoi usare:

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

un'altra alternativa: se conosci le linee che desideri corrispondano a un modello unico:

# 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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.