Como conto as palavras em uma parte de um arquivo, sem sair do vim?


10

Eu tenho um arquivo cheio de texto (por exemplo, Markdown ou LaTeX). Eu gostaria de contar o número de palavras em uma parte deste arquivo.

Eu sei que posso fazer :! wc -w %para executar wc -w no buffer atual. E sei que posso arrancar a seção de interesse em um registro nomeado. Acho que existe uma maneira de enviar um registro nomeado para o sistema operacional para uso em um comando ou canal, mas não consegui encontrar um. Ou existe uma maneira melhor de contar as palavras em um registro?

Meu caso de uso é que eu escrevo bastante não programação (notas, tese, etc.) no vim e gostaria de contar quantas palavras adicionei a uma determinada seção do arquivo no meio de uma edição sessão.

Respostas:


16

Você pode usar gCTRL+g, o que lhe dará:

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

Você também pode usar isso no modo visual, se desejar obter a contagem de palavras apenas para a seleção, o que é especialmente útil combinado com objetos de texto como ip. (por exemplo, você pode usar vipg<C-g>para obter a contagem de palavras do parágrafo atual).

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


A opção acima é provavelmente melhor, mas você também pode usar o wcutilitário para contar o número de palavras em uma seção. Além do :! wc -w %formulário que você usa, você também pode usar :%!wc -w. Isso filtrará um movimento para uma ferramenta shell (nesse caso %, o buffer inteiro), mas você também poderá usar outros intervalos (como :1,5!wc -wnas primeiras 5 linhas, !,+5!wc -wnas atuais e nas próximas 5, etc.). Você também pode selecionar o texto no modo visual e digitar :!wc -wpara filtrar sua seleção.

Observe que isso substituirá o movimento pela saída da ferramenta shell, mas você pode udesfazer isso.

Veja :help :range!, :help rangee esta resposta onde eu dar mais exemplos de intervalos.


Eu havia encontrado algo assim durante a pesquisa, mas perdi que o primeiro g faça parte do comando counting, não um especificador de local. Esta solução faz sentido agora. Aparentemente, eu também deveria ler no modo Visual; Não o uso com frequência suficiente.
Colin McFaul

1
Eu não tinha ideia de que você poderia usar g<C-g>dessa maneira. Impressionante!
EvergreenTree

3

Há duas maneiras de se conseguir isso: a maneira pura de vimscript e a wcmaneira.

A maneira pura do vim

Você pode usar o comando de pesquisa e substituição para fazer isso. Por exemplo:

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

O que isso faz é, em vez de substituir um determinado padrão por algo, apenas conta as ocorrências do padrão. Isso é por causa da nbandeira. Para contar as palavras em uma seção específica (neste caso, linhas 5 a 15), você pode fazer algo assim:

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

Isso elimina a necessidade de puxar o conteúdo de uma seleção para um registro. Para ver mais possibilidades do que pode ser colocado no lugar 5-15, leia o tópico de ajuda para cmdline-ranges. Se você deseja fazer isso com frequência, provavelmente é bom criar um mapeamento (ou comando) para ele. Além disso, se você tiver hlsearchativado, poderá executar :nohlsearchposteriormente para limpar o realce.

O wccaminho

A mesma coisa pode ser realizada com wc. Da mesma maneira que você pode usar cmdline-rangespara selecionar a área com o :scomando, você pode usá-los com comandos externos. Por exemplo:

:5,15!wc -w

Isso executa as linhas 5 a 15 através do wccomando A desvantagem disso é que ele substitui esse intervalo de linhas pela saída do comando. Você pode desfazer essa alteração pressionando u. Observe também que a solução vimscript pode não funcionar com idiomas diferentes, porque \wnão corresponde ao que normalmente seriam caracteres de palavra em outros idiomas. wcpode fazer melhor nisso do que \w. Além disso, aqui está um comando sofisticado para torná-lo mais rápido:

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

Observe que isso derruba o aregistro.

Nota

Parece que isso também pode ser realizado no modo visual com a g<C-g>combinação de teclas. Veja a resposta de Carpetsmoker para uma explicação disso.


Eles precisam ser combinados com n para torná-los globais (caso contrário, eles só correspondem a uma palavra por linha). O segundo também precisa de um s no começo.
Colin McFaul

1
Corrigido, desculpe por isso.
EvergreenTree

1
Usar \wsons como uma boa ideia no começo, mas depois de testá-lo, encontrei vários problemas. O maior é que ele não corresponde a caracteres não-ascii, então uma palavra como überé simplesmente ignorada (houve uma pergunta sobre isso ontem). Além disso, uma palavra como e-mailé contada como 2 palavras, já que -não está em \w(usar a -é um tanto incomum em inglês, mas muito comum em holandês, por exemplo). Pode haver outros personagens que são ignorados desta forma, o que nos leva ao meu último ponto: convenções, como o que é considerado uma "palavra" podem ser diferentes ...
Martin Tournoij

... em vários idiomas, e ferramentas "apropriadas", como wcpodem ser encontradas no local (não sei se o GNU wcrealmente lida com isso a propósito, as ferramentas GNU não são bem conhecidas por seu excelente suporte unicode).
Martin Tournoij 28/06/2015

Isso é interessante. Eu poderia acrescentar isso como uma vantagem à wcsolução.
EvergreenTree

1

Para palavras, use:

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

. indica a linha atual.

Também coloquei o seguinte no meu arquivo .vimrc:

:cabbrev zzcc   s/./&/gn

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

Eu posso digitar:

:.,+6 zzcw

e o zzcwexpandirá paras/\i\+/&/g

O zzcwé apenas um nome estranho que não corresponde a nada (para mim).

Um efeito colateral é que o arquivo inteiro é selecionado e destacado.

Queria poder digitar tweets com várias linhas em um arquivo, garantir que não houvesse muitos caracteres e colar o tweet no twitter.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.