Vim: s sostituisce le prime occorrenze N <g su una riga


13

In ogni caso, a volte ho occasione di sostituire le prime occorrenze di una partita su una linea, ma non a tutti piacerebbe g. per esempio:

a a a a a

per

b b b a a

So che potrei usare :s/a/b/[enter]:[up][enter]:[up][enter], ma è abbastanza noioso in tre ripetizioni, ho linee con potenzialmente più di 10 sostituzioni.
Ho provato:

  • :s/a/b/3g: vim si è lamentato dei personaggi finali.
  • :s/a/b/3: modifica la prima occorrenza su questa e le due righe seguenti.
  • 3:s/a/b: uguale al precedente.
  • :s/a/b/g3: modifica tutte le occorrenze su questa e le due righe successive.
  • :3s/a/b: modifica la prima occorrenza sulla riga 3.
  • :/a/,3/a/s/a/b: modifica la prima occorrenza su ogni riga tra la successiva ae la terza riga contenuta anel file (chiedendo di invertire se necessario).
  • :/a/,/\([^a]*a\)\{3\}/s/a/b/: cambia la prima occorrenza su ogni riga tra questa e la successiva con 3 asecondi (e questo non sarebbe stato facilmente estendibile a una ricerca multi-carattere).

E vari altri schemi di indirizzamento, nessuno dei quali ha funzionato. Devo dire che ho imparato parecchio sul :scomando cercando di trovare una risposta a questo problema, ma non l'ho ancora risolto.

Qualcuno sa come farlo?

(punti bonus per intervallo specifico, ad es. dalla seconda alla quarta occorrenza)


2
Sono abbastanza sicuro che non puoi farlo in vim, ma per renderlo meno noioso, conosci "n" e "." in modalità visiva? Cioè, usi / pattern / per trovare la cosa da cambiare, cambiarla usando "cw" o qualsiasi altra cosa, quindi usa "n" (solo n, senza virgolette) per trovare il modello successivo e premere "." (solo punto, senza virgolette) per eseguire l'ultima modifica.
Bruce Ediger,

@BruceEdiger lo sapevo ne ., anche se non pensavo di usarli qui. Certamente un miglioramento, grazie.
Kevin,

s/a/=something/dovrebbe fare il trucco ( :help sub-replace-=). Non sono abbastanza fluente in Vim da scrivere somethingsubito.
Gilles 'SO- smetti di essere malvagio' il

Nota: :[up][enter]può essere sostituito con &, che non è ancora l'ideale ma almeno è meno doloroso.
Kowh,

Risposte:


10

Basandosi :s/pattern/replacement/gc sull'idea di Samus_ (che sembra essere il modo più semplice per garantire il corretto funzionamento quando il modello è contenuto nella stringa di sostituzione), per sostituire le occorrenze dal 2 ° al 4 ° su una sola riga:

:call feedkeys("nyyyq") | s/pat/string/gc

feedkeys()è una funzione che inserisce la stringa di input nella coda di input della tastiera. Il punto è fare il conteggio in anticipo in modo da non doverti preoccupare di perdere il conto o di essere interrotto.

Per un caso più generale, per sostituire le occorrenze da Mth a Nth su una sola riga per N maggiore o uguale a una M molto grande :

:call feedkeys(repeat("n", M-1) . repeat("y", N-M+1) . "q") | s/pat/string/gc

Sostituisci M e N con i valori che desideri (puoi anche lasciar vimfare la banale aritmetica mentale se non vuoi farlo da solo). Si noti che .è l'operatore di concatenazione di stringhe di VimL. Ovviamente questo consente di risparmiare solo la pressione dei tasti per la M grande . Se si utilizza questa funzionalità frequentemente, potrebbe farti risparmiare tempo per inserire quanto sopra in un comando personalizzato o una funzione di qualche tipo, poiché è abbastanza da digitare.


Hmm. Mi piace questa. Dovrei essere in grado di scrivere una funzione anche per questo.
Kevin

8

Per la prima domanda farei:

:s/a/b
&&

Il secondo è più complicato, non conosco un modo per farlo automaticamente, ma puoi fare in modo che Vim ti spinga ad ogni partita in questo modo:

:s/a/b/gc

Quindi rispondi "no" alle prime n corrispondenze e "sì" alle altre.


Ho dimenticato cche potrebbe essere la migliore soluzione ancora proposta. Dovrei ancora contare, ma penso che sia la prima opzione che funzionerebbe con le sostituzioni che contengono la stringa di ricerca.
Kevin,

6
a a a a a
a a a a a
a a a a a
a a a a a
a a a a a
a a a a a
a a a a a

:3,6g/^/let i=0 | while i<3 | s/a/b/ | let i+=1 | endwhile

a a a a a
a a a a a
b b b a a
b b b a a
b b b a a
b b b a a
a a a a a

1
Questo è buono, ma soffre ancora del problema sottolineato da Gilles (su un altro post, che da allora sembra essere stato eliminato), che funziona solo se la sostituzione non contiene lo schema. Anche se mi piace l'idea di scripting.
Kevin,

Una cosa di bellezza!
vescovo,

1

Penso che potrebbe funzionare, sostituire prima, quindi ripetere 2 volte:

:s/a/b/
2@:
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.