Come contare le parole in una parte di un file, senza lasciare VIM?


10

Ho un file pieno di testo (ad esempio Markdown o LaTeX). Vorrei contare il numero di parole in una parte di questo file.

So che posso fare :! wc -w %per eseguire wc -w sul buffer corrente. E so che posso spostare la sezione di interesse in un registro denominato. Immagino che ci sia un modo per inviare un registro denominato al sistema operativo da utilizzare in un comando o pipe, ma non sono stato in grado di trovarne uno. O c'è un modo migliore per contare le parole in un registro?

Il mio caso d'uso è che faccio un sacco di scrittura non programmabile (note, tesi, ecc.) In Vim, e vorrei contare quante parole ho aggiunto a una determinata sezione del file nel mezzo di una modifica sessione.

Risposte:


16

Puoi usare gCTRL+g, che ti darà:

Col 1 of 118-121; Line 1 of 5; Word 1 of 142; Byte 1 of 678

Puoi anche usarlo dalla modalità visiva, se vuoi ottenere il conteggio delle parole solo per la selezione, che è particolarmente utile combinato con oggetti di testo come ip. (ad es. è possibile utilizzare vipg<C-g>per ottenere il conteggio delle parole del paragrafo corrente).

Vedi: :help word-counte :help text-objects.


L'opzione sopra è probabilmente migliore, ma puoi anche usare l' wcutilità per contare il numero di parole in una sezione. Oltre al :! wc -w %modulo che usi, puoi anche usare :%!wc -w. Questo filtrerà un movimento su uno strumento shell (in questo caso %, l'intero buffer), ma puoi anche usare altri intervalli (come :1,5!wc -wper le prime 5 righe, !,+5!wc -wper le attuali 5 e successive, ecc.). Puoi anche selezionare il testo in modalità visiva e digitare :!wc -wper filtrare la selezione.

Nota che questo sostituirà il movimento con l'output dello strumento shell, ma puoi uannullarlo.

Vedi :help :range!, :help rangee questa risposta in cui fornisco altri esempi di intervalli.


Durante la ricerca avevo trovato qualcosa del genere, ma mi mancava che la prima g facesse parte del comando di conteggio, non un identificatore di posizione. Questa soluzione ha senso ora. Apparentemente dovrei anche leggere in modalità visiva; Non lo uso abbastanza spesso.
Colin McFaul,

1
Non avevo idea che tu potessi usare in g<C-g>quel modo. Eccezionale!
EvergreenTree,

3

Ci sono due modi in cui questo può essere realizzato, il modo puro vimscript e il wcmodo.

La via pura

È possibile utilizzare il comando cerca e sostituisci per fare ciò. Per esempio:

:%s/\<\w\{-}\>//gn

Ciò che fa invece di sostituire un determinato modello con qualcosa, conta solo le occorrenze del modello. Questo è a causa della nbandiera. Per contare le parole in una sezione specifica (in questo caso le righe da 5 a 15), potresti fare qualcosa del genere:

:5,15s/\<\w\{-}\>//gn

Ciò elimina la necessità di trascinare il contenuto di una selezione in un registro. Per vedere più possibilità per ciò che può essere messo al posto di 5-15, leggere l'argomento della guida per cmdline-ranges. Se vuoi farlo spesso, probabilmente è bene creare una mappatura (o comando) per questo. Inoltre, se hai hlsearchabilitato, potresti voler correre in :nohlsearchseguito per cancellare l'evidenziazione.

La wcstrada

La stessa cosa può essere realizzata con wc. Allo stesso modo è possibile utilizzare cmdline-rangesper selezionare l'area con il :scomando, è possibile utilizzarli con comandi esterni. Per esempio:

:5,15!wc -w

Ciò esegue le righe da 5 a 15 tramite il wccomando. L'aspetto negativo di questo è che sostituisce quell'intervallo di righe con l'output del comando. È possibile annullare questa modifica premendo u. Si noti inoltre che la soluzione vimscript potrebbe non funzionare con lingue diverse, poiché \wnon corrisponde a quelli che normalmente sarebbero caratteri di parole in altre lingue. wcpotrebbe fare di meglio \w. Inoltre, ecco un comando elaborato per rendere più veloce l'operazione:

command -range=% -addr=lines WordCount execute '<count>!wc -w' | .y a | undo | echo @a

Si noti che questo blocca il aregistro.

Nota

Sembra che ciò possa essere realizzato anche in modalità visiva con la g<C-g>combinazione di tasti. Vedi la risposta di Carpetsmoker per una spiegazione di questo.


Questi hanno bisogno di una g insieme a n per renderli globali (altrimenti, corrispondono solo a una parola per riga). Il secondo ha anche bisogno di una s all'inizio.
Colin McFaul,

1
Risolto, mi dispiace per quello.
EvergreenTree,

1
All'inizio \wsembra una buona idea, ma dopo averlo provato ho riscontrato una serie di problemi. Il più grande è che non corrisponderà a caratteri non ascii, quindi una parola come überviene semplicemente ignorata ( ieri c'era una domanda al riguardo ). Inoltre, una parola come e-mailviene contata come 2 parole, poiché -non è presente \w(l'utilizzo di a -è in qualche modo insolito in inglese, ma molto comune in olandese per esempio). Potrebbero esserci altri personaggi che vengono ignorati in questo modo, il che ci porta al mio ultimo punto: le convenzioni su ciò che è considerato una "parola" possono differire ...
Martin Tournoij,

... in varie lingue, e strumenti "corretti" come wcpossono essere presi in considerazione dalle impostazioni locali (non so se GNU in wcrealtà si occuperà di questo a proposito, gli strumenti GNU non sono ben noti per il loro eccellente supporto Unicode).
Martin Tournoij,

È interessante. Potrei aggiungere questo come un vantaggio alla wcsoluzione.
EvergreenTree,

1

Per parole usare:

:.,+4 s/\i\+/&/gn

. indica la linea corrente.

Inoltre ho inserito quanto segue nel mio file .vimrc:

:cabbrev zzcc   s/./&/gn

:cabbrev zzcw   s/\i\+/&/g

Posso scrivere:

:.,+6 zzcw

e la zzcwsi espanderà as/\i\+/&/g

Il zzcwè solo un nome strano che non sarà mai soddisfatta (per me).

Un effetto collaterale è che l'intero file è selezionato ed evidenziato.

Volevo essere in grado di digitare tweet su più righe in un file, assicurarmi che non ci fossero troppi caratteri e incollare il tweet su Twitter.

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.