Come aggiungere numeri di riga permanenti a un file?


22

Ho un file di testo come questo (usando gVim su Windows)

foo bar baz quux 
corge grault garply 
waldo fred plugh 
[...150 more lines...]
xyzzy thud

Voglio aggiungere un numero a ciascuna riga del file. Non utilizzando :set number, ma per aggiungere il numero come testo che precede ciascuna riga, come segue, quindi il numero fa parte del file.

1. foo bar baz quux 
2. corge grault garply 
3. waldo fred plugh 
[...~150 more lines...]
155. xyzzy thud

awkè probabilmente lo strumento per questo lavoro. Ma sono su Windows (sospiro).
roblogic,

Risposto già qui , non importa :)
roblogic

1
Forse .. O è più generale?
muru,

È simile, ma non saprei cosa sono i numeri di riga permanenti. In secondo luogo, l'altra domanda riguarda tutte le righe (e la risposta lo fa) per gVim in particolare su Windows e questo è un semplice elenco numerato per un paragrafo solo in formato chiaro.
Kenorb,

3
Bene, immagino che il post utilizzi "permanente" per indicare che il buffer deve essere modificato e che i numeri non sono qualcosa di puramente visivo (uguale a te). Il motivo per specificare gvim su Windows è evitare utility esterne come cato nl, che possono fare linee di numero, ma non sono generalmente disponibili su Windows (come OP indica dal loro commento su awk). Le prime due soluzioni sono Vim puro. Infine, tutte le linee vs un para sono solo una questione di selezione dell'intervallo. Chiaramente non è un grosso problema.
muru,

Risposte:


37

In puro stile Vim:

:%s/^/\=line('.').". "

Spiegazione:

:%s/^/            " the substitution will be applied to the beginning of every line
\=                " the rest of the replacement part is an expression
line('.').". "    " the expression returns the current line number concatenated with a dot and a space

Vedi :help \=e :help line().

L'uso di un'espressione nella parte di sostituzione è molto potente e FWIW è un ottimo punto di accesso a vimscript.


Come posso aggiungere questo comando molto utile a una keymap in vimrc?
Cosmicraga,

Per accedere all'argomento della guida di Vim per la sostituzione::help sub-replace-expression
akurtser

9

Una cosa bella delle macro di Vim è che possono ricorrere (possono invocare se stessi):

  1. Cancella registro q: qqq
  2. Aggiungi il numero alla prima riga: ggI1.(non dimenticare lo spazio!)
  3. Torna indietro all'inizio della riga e inizia a registrare una macro: 0qq
  4. Copia il numero: yW
  5. Spostati verso il basso di una riga e incolla il numero: +P
  6. Torna all'inizio della riga e incrementa il numero: 0<c-a>
  7. Torna all'inizio della riga (quindi la macro non si interrompe quando arriva a doppie cifre!): 0
  8. Chiamare la macro una volta, per renderla ricorsiva. A questo punto, non c'è ancora nulla nel registro q, quindi non accadrà nulla: @q.
  9. Salva la macro: q
  10. Chiama ancora una volta la macro e guarda le scintille volare !: @@

La macro continuerà quindi a richiamare se stessa fino a raggiungere la fine del file.

Puoi usare il trucco macro ricorsivo per molti altri problemi simili, quindi è bene esserne consapevoli.

Se non si desidera utilizzare una macro ricorsiva per qualche motivo, è possibile omettere i passaggi 1 e 8 e utilizzare un conteggio per eseguire la macro più volte, ad esempio 100@qeseguirà la macro q100 volte.


1
Roba potente, mi inchino alla tua padronanza. Le macro sono come una magia nera per me ...
roblogic

1
@ropata, una macro è solo una sequenza di comandi (principalmente) in modalità normale.
romainl,

1
@romainl Penso che sia meglio pensarlo come una sequenza di tasti .
Ricco

2
@Rich, può essere una sequenza di molte cose, inclusi gli ex comandi.
romainl,

2
@romainl Sì, ecco perché penso sia meglio pensarlo come una sequenza di tasti. Riproduce esattamente ciò che digiti sulla tastiera (compresi, come dici tu, ex comandi), come se avessi digitato tutto manualmente.
Ricco

7

Mi piace usare il comando globale vim per eseguire attività come questa. Questo si applica all'aggiunta dell'iterazione all'inizio di una riga o alla modifica di un simbolo nel testo. Sembra più complicato rispetto alle altre soluzioni, ma è un modello abbastanza flessibile da usare quando lo hai a portata di mano ed è facile da modificare senza pensarci troppo.

Innanzitutto, scegli il tuo intervallo (quali linee vuoi applicare). Di solito uso i segni (ad es. maSulla prima riga e mbsulla seconda, ma puoi anche usare i numeri di riga o la selezione visiva), quindi inserisco una modifica del seguente comando (attualmente ottimizzato per il tuo caso d'uso)

:let i=1|'a,'bg/^/s/^/\=i.". "/|let i=i+1

Deconstruction

:let i=1

Questo imposta la variabile icon un valore iniziale. Di solito le liste iniziano con 1, quindi sto impostando i su 1.

|

La barra avvia un nuovo comando

'a,'b

Questo imposta l'intervallo del comando successivo. Vado da un segno aall'altro b, che verrebbe impostato sulla prima riga e sull'ultima riga del tuo elenco.

g/^/

Questo è il comando globale. Cerca nel file (o intervallo) una determinata espressione regolare ed eseguirà il resto della riga di comando su ciascuna delle righe corrispondenti. Sto abbinando ogni riga cercando "inizio riga". Se avessi del testo come

Item some txt
other text

Item second item
whatever
Item third

e voglio solo mettere queste etichette davanti Iteme ignorare le altre linee, fare g/Item/o g/^Item/invece (assumendo il testo letterale dell'articolo)

s/^/\=i.". "/

Ciò esegue l'espressione regolare per sostituire l'inizio della riga con il valore di iconcatenato con a .. Generalmente puoi farlo a qualsiasi cosa (sostituisci l'etichetta Itemcon il numero, per esempio).

|let i=i+1

Anche se la barra avvia un nuovo comando, imposta un secondo comando da eseguire all'interno del comando globale, anziché dopo che il globale è completo. Il risultato è un incremento iprima che la riga successiva venga elaborata da g. Ecco un altro luogo di flessibilità. La modifica di i può essere qualsiasi cosa (incremento di 2, chiama una funzione che genera l'elemento successivo della sequenza di Fibonacci, qualunque cosa).


7

Aggiungi numeri a tutte le righe

È possibile utilizzare :%!nl -bao :%!cat -ncomandi che aggiungeranno numeri di riga a tutte le righe.

Su Windows, devi avere installato Cygwin / MSYS / SUA.

Aggiungi numeri alle linee selezionate

Per aggiungere numeri solo per le linee selezionate, selezionale in modalità visiva ( ve cursori), quindi, una volta terminato, esegui il comando: :%!nl(ignora le righe vuote) o :%!cat -n(incluse le righe vuote).

Formattazione

Per rimuovere spazi aggiuntivi, selezionali nel blocco visivo ( Ctrl+ v) e rimuovili ( x).

Per aggiungere alcuni caratteri ( ., :, )) dopo i numeri, selezionarli nel blocco visiva ( Ctrl+ v), quindi aggiungere il carattere ( Adigitare il carattere, poi finire con Esc).


2
Ciò non fornisce la stessa formattazione fornita nella domanda. Tuttavia, mi piace la semplicità della soluzione.
Karl Yngve Lervåg,

@ KarlYngveLervåg Grazie, incluso nella risposta.
Kenorb,

5

Una modifica della risposta di Romainl :

:%s/^\(\d\+\. \)\?/\=line('.').". "

Questo non solo aggiungerà i numeri di riga, ma sostituirà anche i numeri di riga in uscita se sono già lì. Di, se hai inserito una linea a metà strada, rinumererà tutto come previsto.

Funziona sostituendo qualsiasi numero seguito da a. e uno spazio all'inizio della riga con un nuovo numero. Questo ovviamente si interromperà se hai una linea che inizia già con questo schema, quindi usa con il pensiero.

La parte aggiunta:

  • ^ - Inizio della linea
  • \( - Avvia un nuovo sottogruppo
  • \d\+ - Abbina una cifra una o più volte
  • \. - Abbina un punto ( .) e uno spazio .
  • \) - Fine sottogruppo
  • \? - Rendi il gruppo opzionale, in modo che funzioni come prima se non ci sono ancora numeri su questa linea.

Suggerimento bonus:
per rimuovere i numeri di riga, è possibile utilizzare lo stesso modello con la parte di repalce vuota:

:%s/^\(\d\+\. \)\?//

5
I1. <esc>^qqyWjP^<C-a>q

Questo numera le prime due righe e puoi premere @qper numerare le righe successive (o digitare es. 18@qSe vuoi numerare 20 righe in totale).

Spiegazione:

I1. <esc>  Number the first line
hqq        Go back to the start of the line and start recording a macro
yWjP       Copy the line number to the next line
^<C-a>     Increment the next line's line number
q          Finish recording

Il vantaggio è che non richiede alcun comando esterno, il che è utile, ad esempio, se lavori con Vim su Windows.


Dopo aver digitato 1. <esc>hti trovi nella seconda colonna, non nella prima colonna. Vorrei sostituire il hcon 0, dopo di che penso che la tua soluzione dovrebbe essere molto buona.
Karl Yngve Lervåg,

@ KarlYngveLervåg Whoops, era un errore di battitura. Grazie, risolto.
Maniglia della porta

Nessun problema. Tuttavia, non hai ancora aggiornato la spiegazione. Inoltre: su molte tastiere, ^attende un secondo carattere per consentire combinazioni di caratteri simili ^a -> â. Sono ancora d'accordo che sia la soluzione migliore, ma penso che anche questo dovrebbe essere menzionato.
Karl Yngve Lervåg,

3

Penso che la risposta scelta sia la migliore, ma a livello di varietà, offrirò un'alternativa usando un programma esterno:

:%!cat -n

Questo filtrerà l'intero buffer (come indicato da %) attraverso il programma esterno cat, dove il -nflag antepone ogni riga di input con un numero di riga.

Ciò, ovviamente, richiede l' catinstallazione, il che è vero per (probabilmente) tutti i sistemi simili a Unix.

Controlla :help :range!per maggiori dettagli sul filtraggio attraverso programmi esterni.


1
Mi rendo conto che il richiedente sta usando gVim su Windows, quindi questa soluzione probabilmente non funzionerà lì. Tuttavia, penso che fornisca ancora qualche opportunità per gli altri di imparare da esso.
Tommaso,

Se lo hai installato msysgite aggiunto al tuo PATH (IIRC è un'opzione di installazione), questa soluzione dovrebbe funzionare anche su Windows.
Martin Tournoij,

4
cat -nnon è POSIX, ma lo nlè, quindi potrebbe essere un'opzione migliore.
muru,

2

Una soluzione un po 'hacker potrebbe essere la seguente (tutto ciò che è scritto tra <e> deve essere inserito dopo aver premuto Ctrl+ v):

:%normal :redir @"<Enter>:-=<Enter>:redir END<Enter>I<C-R>".<Tab><Esc>kdd

Deconstruction

:%normal {commands}

esegue il comando in modalità normale su ogni riga specificata dall'intervallo, in questo caso ogni riga

:redir @"

reindirizza ogni output creato da ex comandi al buffer senza nome.

:.=

è un comando ex che genera il numero di riga corrente (purtroppo con una nuova riga precedente)

:redir END

interrompe il reindirizzamento al buffer senza nome

I<C-R>".<Tab><Esc>

inserisce il contenuto del buffer senza nome con a. e una scheda all'inizio di ogni riga ed esce dalla modalità di inserimento.

kdd

fa una riga e rimuove la nuova riga che è il risultato del comando:. =.

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.